Full Code of nulrich/RCTAutoComplete for AI

master 9efe9ac88405 cached
25 files
112.4 KB
26.7k tokens
7 symbols
1 requests
Download .txt
Repository: nulrich/RCTAutoComplete
Branch: master
Commit: 9efe9ac88405
Files: 25
Total size: 112.4 KB

Directory structure:
gitextract_dsah9vym/

├── .flowconfig
├── .gitignore
├── .npmignore
├── AutoCompleteView.h
├── AutoCompleteView.m
├── DictionaryAutoCompleteObject.h
├── DictionaryAutoCompleteObject.m
├── LICENSE
├── MLPAutoCompleteTextField/
│   ├── MLPAutoCompleteTextField.h
│   ├── MLPAutoCompleteTextField.m
│   ├── MLPAutoCompleteTextFieldDataSource.h
│   ├── MLPAutoCompleteTextFieldDelegate.h
│   ├── MLPAutoCompletionObject.h
│   ├── NSString+Levenshtein.h
│   └── NSString+Levenshtein.m
├── RCTAutoComplete.android.js
├── RCTAutoComplete.h
├── RCTAutoComplete.ios.js
├── RCTAutoComplete.m
├── RCTAutoComplete.xcodeproj/
│   └── project.pbxproj
├── RCTTableViewCell.h
├── RCTTableViewCell.m
├── README.md
├── package.json
└── react-native-autocomplete.podspec

================================================
FILE CONTENTS
================================================

================================================
FILE: .flowconfig
================================================
[ignore]

# We fork some components by platform.
.*/*.web.js
.*/*.android.js

# Some modules have their own node_modules with overlap
.*/node_modules/node-haste/.*

# Ignore react-tools where there are overlaps, but don't ignore anything that
# react-native relies on
.*/node_modules/react-tools/src/vendor/core/ExecutionEnvironment.js
.*/node_modules/react-tools/src/browser/eventPlugins/ResponderEventPlugin.js
.*/node_modules/react-tools/src/browser/ui/React.js
.*/node_modules/react-tools/src/core/ReactInstanceHandles.js
.*/node_modules/react-tools/src/event/EventPropagators.js

# Ignore commoner tests
.*/node_modules/commoner/test/.*

# See https://github.com/facebook/flow/issues/442
.*/react-tools/node_modules/commoner/lib/reader.js

# Ignore jest
.*/react-native/node_modules/jest-cli/.*

[include]

[libs]
node_modules/react-native/Libraries/react-native/react-native-interface.js

[options]
module.system=haste

[version]
0.11.0


================================================
FILE: .gitignore
================================================
# OSX
#
.DS_Store

# Xcode
#
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate
project.xcworkspace

# node.js
#
node_modules/
npm-debug.log


================================================
FILE: .npmignore
================================================
# OSX
#
.DS_Store

# Xcode
#
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate

# node.js
#
node_modules/
npm-debug.log


================================================
FILE: AutoCompleteView.h
================================================
#import <UIKit/UIKit.h>
#import "MLPAutoCompleteTextField/MLPAutoCompleteTextField.h"

@class RCTEventDispatcher;


@interface AutoCompleteView : MLPAutoCompleteTextField <UITextFieldDelegate>

@property (nonatomic, copy) NSString *cellComponent;

@property (retain, nonatomic) NSArray *suggestions;
@property (copy) void (^handler)(NSArray *);

@property (nonatomic, assign) BOOL caretHidden;
@property (nonatomic, assign) BOOL autoCorrect;
@property (nonatomic, assign) BOOL selectTextOnFocus;
@property (nonatomic, assign) BOOL blurOnSubmit;
@property (nonatomic, assign) UIEdgeInsets contentInset;
@property (nonatomic, strong) UIColor *placeholderTextColor;
@property (nonatomic, assign) NSInteger mostRecentEventCount;
@property (nonatomic, strong) NSNumber *maxLength;

- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher NS_DESIGNATED_INITIALIZER;

- (void)textFieldDidChange;

@end


================================================
FILE: AutoCompleteView.m
================================================
#import "AutoCompleteView.h"
#import "DictionaryAutoCompleteObject.h"

#import "MLPAutoCompleteTextField/MLPAutoCompleteTextField.h"
#import <React/RCTConvert.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTUtils.h>
#import "UIView+React.h"

@implementation AutoCompleteView
{
    RCTEventDispatcher *_eventDispatcher;
    NSMutableArray *_reactSubviews;
    BOOL _jsRequestingFirstResponder;
    NSInteger _nativeEventCount;
    NSInteger _mostRecentEventCount;
}

- (void) setSuggestions:(NSArray *)completions {
    if (self.handler) {
        if (self.cellComponent !=nil) {
            NSMutableArray *mutableJsonObjects = [NSMutableArray new];
            for(NSDictionary *json in completions){
                DictionaryAutoCompleteObject *jsonObject = [[DictionaryAutoCompleteObject alloc] initWithDictionnary:json];
                [mutableJsonObjects addObject:jsonObject];
            }
      
          self.handler([NSArray arrayWithArray:mutableJsonObjects]);
        } else {
          self.handler(completions);
        }
    }
}

- (void) setMostRecentEventCount:(NSInteger)mostRecentEventCount {
    if (mostRecentEventCount > 0) {
        _mostRecentEventCount = mostRecentEventCount;
    }
}

- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
{
    if ((self = [super initWithFrame:CGRectZero])) {
        RCTAssert(eventDispatcher, @"eventDispatcher is a required parameter");
        _eventDispatcher = eventDispatcher;
        [self addTarget:self action:@selector(textFieldDidChange) forControlEvents:UIControlEventEditingChanged];
        [self addTarget:self action:@selector(textFieldBeginEditing) forControlEvents:UIControlEventEditingDidBegin];
        [self addTarget:self action:@selector(textFieldEndEditing) forControlEvents:UIControlEventEditingDidEnd];
        [self addTarget:self action:@selector(textFieldSubmitEditing) forControlEvents:UIControlEventEditingDidEndOnExit];
        _reactSubviews = [NSMutableArray new];
    }
    return self;
}

RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame)
RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)


- (void)setText:(NSString *)text
{
    NSInteger eventLag = _nativeEventCount - _mostRecentEventCount;
    if (eventLag == 0 && ![text isEqualToString:self.text]) {
        UITextRange *selection = self.selectedTextRange;
        super.text = text;
        self.selectedTextRange = selection; // maintain cursor position/selection - this is robust to out of bounds
    } else if (eventLag > RCTTextUpdateLagWarningThreshold) {
        RCTLogWarn(@"Native TextInput(%@) is %zd events ahead of JS - try to make your JS faster.", self.text, eventLag);
    }
}

static void RCTUpdatePlaceholder(AutoCompleteView *self)
{
    if (self.placeholder.length > 0 && self.placeholderTextColor) {
        self.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.placeholder
                                                                     attributes:@{
                                                                                  NSForegroundColorAttributeName : self.placeholderTextColor
                                                                                  }];
    } else if (self.placeholder.length) {
        self.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.placeholder];
    }
}

- (void)setPlaceholderTextColor:(UIColor *)placeholderTextColor
{
    _placeholderTextColor = placeholderTextColor;
    RCTUpdatePlaceholder(self);
}

- (void)setPlaceholder:(NSString *)placeholder
{
    super.placeholder = placeholder;
    RCTUpdatePlaceholder(self);
}

- (NSArray *)reactSubviews
{
    // TODO: do we support subviews of textfield in React?
    // In any case, we should have a better approach than manually
    // maintaining array in each view subclass like this
    return _reactSubviews;
}

- (void)removeReactSubview:(UIView *)subview
{
    // TODO: this is a bit broken - if the TextField inserts any of
    // its own views below or between React's, the indices won't match
    [_reactSubviews removeObject:subview];
    [subview removeFromSuperview];
}

- (void)insertReactSubview:(UIView *)view atIndex:(NSInteger)atIndex
{
    // TODO: this is a bit broken - if the TextField inserts any of
    // its own views below or between React's, the indices won't match
    [_reactSubviews insertObject:view atIndex:atIndex];
    [super insertSubview:view atIndex:atIndex];
}

- (CGRect)caretRectForPosition:(UITextPosition *)position
{
    if (_caretHidden) {
        return CGRectZero;
    }
    return [super caretRectForPosition:position];
}

- (CGRect)textRectForBounds:(CGRect)bounds
{
    CGRect rect = [super textRectForBounds:bounds];
    return UIEdgeInsetsInsetRect(rect, _contentInset);
}

- (CGRect)editingRectForBounds:(CGRect)bounds
{
    return [self textRectForBounds:bounds];
}

- (void)setAutoCorrect:(BOOL)autoCorrect
{
    self.autocorrectionType = (autoCorrect ? UITextAutocorrectionTypeYes : UITextAutocorrectionTypeNo);
}

- (BOOL)autoCorrect
{
    return self.autocorrectionType == UITextAutocorrectionTypeYes;
}

- (void)textFieldDidChange
{
    _nativeEventCount++;
    [_eventDispatcher sendTextEventWithType:RCTTextEventTypeChange
                                   reactTag:self.reactTag
                                       text:self.text
                                        key:nil
                                 eventCount:_nativeEventCount];
}

- (void)textFieldEndEditing
{
    [_eventDispatcher sendTextEventWithType:RCTTextEventTypeEnd
                                   reactTag:self.reactTag
                                       text:self.text
                                        key:nil
                                 eventCount:_nativeEventCount];
}
- (void)textFieldSubmitEditing
{
    [_eventDispatcher sendTextEventWithType:RCTTextEventTypeSubmit
                                   reactTag:self.reactTag
                                       text:self.text
                                        key:nil
                                 eventCount:_nativeEventCount];
}

- (void)textFieldBeginEditing
{
    if (_selectTextOnFocus) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [self selectAll:nil];
        });
    }
    [_eventDispatcher sendTextEventWithType:RCTTextEventTypeFocus
                                   reactTag:self.reactTag
                                       text:self.text
                                        key:nil
                                 eventCount:_nativeEventCount];
}

- (BOOL)becomeFirstResponder
{
    _jsRequestingFirstResponder = YES;
    BOOL result = [super becomeFirstResponder];
    _jsRequestingFirstResponder = NO;
    return result;
}

- (BOOL)resignFirstResponder
{
    BOOL result = [super resignFirstResponder];
    if (result)
    {
        [_eventDispatcher sendTextEventWithType:RCTTextEventTypeBlur
                                       reactTag:self.reactTag
                                           text:self.text
                                            key:nil
                                     eventCount:_nativeEventCount];
    }
    return result;
}

- (BOOL)canBecomeFirstResponder
{
    return _jsRequestingFirstResponder;
}

@end


================================================
FILE: DictionaryAutoCompleteObject.h
================================================
#import <Foundation/Foundation.h>
#import "MLPAutoCompletionObject.h"

@interface DictionaryAutoCompleteObject : NSObject <MLPAutoCompletionObject>
    @property (strong) NSDictionary *json;

    - (id)initWithDictionnary:(NSDictionary *)json;
@end


================================================
FILE: DictionaryAutoCompleteObject.m
================================================
#import "DictionaryAutoCompleteObject.h"

@interface DictionaryAutoCompleteObject ()
@end

@implementation DictionaryAutoCompleteObject


- (id)initWithDictionnary:(NSDictionary *)json
{
    self = [super init];
    if (self) {
        [self setJson:json];
    }
    return self;
}

#pragma mark - MLPAutoCompletionObject Protocol

- (NSString *)autocompleteString
{
    return @"";
}

@end


================================================
FILE: LICENSE
================================================
Copyright (c) 2015 Nicolas Ulrich

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.


================================================
FILE: MLPAutoCompleteTextField/MLPAutoCompleteTextField.h
================================================
/*
 //  MLPAutoCompleteTextField.h
 //
 //
 //  Created by Eddy Borja on 12/29/12.
 //  Copyright (c) 2013 Mainloop LLC. All rights reserved.
 
 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 
 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */


#import <UIKit/UIKit.h>
#import "MLPAutoCompleteTextFieldDataSource.h"
#import "MLPAutoCompleteTextFieldDelegate.h"

@protocol MLPAutoCompleteSortOperationDelegate <NSObject>
- (void)autoCompleteTermsDidSort:(NSArray *)completions;
- (NSInteger)maximumEditDistanceForAutoCompleteTerms;
@end

@protocol MLPAutoCompleteFetchOperationDelegate <NSObject>
- (void)autoCompleteTermsDidFetch:(NSDictionary *)fetchInfo;
@end


@interface MLPAutoCompleteTextField : UITextField <UITableViewDataSource, UITableViewDelegate, MLPAutoCompleteSortOperationDelegate, MLPAutoCompleteFetchOperationDelegate>

+ (NSString *) accessibilityLabelForIndexPath:(NSIndexPath *)indexPath;

@property (strong, readonly) UITableView *autoCompleteTableView;

// all delegates and datasources should be weak referenced
@property (weak) IBOutlet id <MLPAutoCompleteTextFieldDataSource> autoCompleteDataSource;
@property (weak) IBOutlet id <MLPAutoCompleteTextFieldDelegate> autoCompleteDelegate;


@property (assign) NSTimeInterval autoCompleteFetchRequestDelay; //default is 0.1, if you fetch from a web service you may want this higher to prevent multiple calls happening very quickly.
@property (assign) BOOL sortAutoCompleteSuggestionsByClosestMatch;
@property (assign) BOOL applyBoldEffectToAutoCompleteSuggestions;
@property (assign) BOOL reverseAutoCompleteSuggestionsBoldEffect;
@property (assign) BOOL showTextFieldDropShadowWhenAutoCompleteTableIsOpen;
@property (assign) BOOL showAutoCompleteTableWhenEditingBegins; //only applies for drop down style autocomplete tables.
@property (assign) BOOL disableAutoCompleteTableUserInteractionWhileFetching;
@property (assign) BOOL autoCompleteTableAppearsAsKeyboardAccessory; //if set to TRUE, the autocomplete table will appear as a keyboard input accessory view rather than a drop down.
@property (assign) BOOL shouldResignFirstResponderFromKeyboardAfterSelectionOfAutoCompleteRows; // default is TRUE
@property (assign) NSInteger maximumEditDistance; //This is the maximum amount of edits allowed for a word to be considered as a possible autocomplete suggestion to the user input. Set this to 0 to require an exact match of the user input so far. Defaults to 100.

@property (assign) BOOL requireAutoCompleteSuggestionsToMatchInputExactly; //If true, the only suggestions that are shown will be words that complete the currently user input (This is the same as a maximumEditDistance of 0). Defaults to false to take typos into consideration.

@property (assign) BOOL autoCompleteTableViewHidden;

@property (assign) CGFloat autoCompleteFontSize;
@property (strong) NSString *autoCompleteBoldFontName;
@property (strong) NSString *autoCompleteRegularFontName;

@property (assign) NSInteger maximumNumberOfAutoCompleteRows;
@property (assign) CGFloat partOfAutoCompleteRowHeightToCut; // this number multiplied by autoCompleteRowHeight will be subtracted from total tableView height.
@property (assign) CGFloat autoCompleteRowHeight;
@property (nonatomic, assign) CGRect autoCompleteTableFrame;
@property (assign) CGSize autoCompleteTableOriginOffset;
@property (assign) CGSize autoCompleteTableSizeOffset;
@property (assign) CGFloat autoCompleteTableCornerRadius; //only applies for drop down style autocomplete tables.
@property (nonatomic, assign) UIEdgeInsets autoCompleteContentInsets;
@property (nonatomic, assign) UIEdgeInsets autoCompleteScrollIndicatorInsets;
@property (nonatomic, strong) UIColor *autoCompleteTableBorderColor;
@property (nonatomic, assign) CGFloat autoCompleteTableBorderWidth;
@property (nonatomic, strong) UIColor *autoCompleteTableBackgroundColor;
@property (strong) UIColor *autoCompleteTableCellBackgroundColor;
@property (strong) UIColor *autoCompleteTableCellTextColor;


- (void)registerAutoCompleteCellNib:(UINib *)nib forCellReuseIdentifier:(NSString *)reuseIdentifier;

- (void)registerAutoCompleteCellClass:(Class)cellClass forCellReuseIdentifier:(NSString *)reuseIdentifier;

- (void)reloadData; //it will ask DataSource for data again
@end



================================================
FILE: MLPAutoCompleteTextField/MLPAutoCompleteTextField.m
================================================
/*
 //  MLPAutoCompleteTextField.m
 //
 //
 //  Created by Eddy Borja on 12/29/12.
 //  Copyright (c) 2013 Mainloop LLC. All rights reserved.
 
 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 
 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#import "MLPAutoCompleteTextField.h"
#import "MLPAutoCompletionObject.h"
#import "NSString+Levenshtein.h"
#import <QuartzCore/QuartzCore.h>


static NSString *kSortInputStringKey = @"sortInputString";
static NSString *kSortEditDistancesKey = @"editDistances";
static NSString *kSortObjectKey = @"sortObject";
static NSString *kKeyboardAccessoryInputKeyPath = @"autoCompleteTableAppearsAsKeyboardAccessory";
const NSTimeInterval DefaultAutoCompleteRequestDelay = 0.1;

@interface MLPAutoCompleteSortOperation: NSOperation
@property (strong) NSString *incompleteString;
@property (strong) NSArray *possibleCompletions;
@property (strong) id <MLPAutoCompleteSortOperationDelegate> delegate;
@property (strong) NSDictionary *boldTextAttributes;
@property (strong) NSDictionary *regularTextAttributes;

- (id)initWithDelegate:(id<MLPAutoCompleteSortOperationDelegate>)aDelegate
      incompleteString:(NSString *)string
   possibleCompletions:(NSArray *)possibleStrings;

- (NSArray *)sortedCompletionsForString:(NSString *)inputString
                    withPossibleStrings:(NSArray *)possibleTerms;
@end

static NSString *kFetchedTermsKey = @"terms";
static NSString *kFetchedStringKey = @"fetchInputString";
@interface MLPAutoCompleteFetchOperation: NSOperation
@property (strong) NSString *incompleteString;
@property (strong) MLPAutoCompleteTextField *textField;
@property (strong) id <MLPAutoCompleteFetchOperationDelegate> delegate;
@property (strong) id <MLPAutoCompleteTextFieldDataSource> dataSource;

- (id)initWithDelegate:(id<MLPAutoCompleteFetchOperationDelegate>)aDelegate
 completionsDataSource:(id<MLPAutoCompleteTextFieldDataSource>)aDataSource
 autoCompleteTextField:(MLPAutoCompleteTextField *)aTextField;

@end


static NSString *kBorderStyleKeyPath = @"borderStyle";
static NSString *kAutoCompleteTableViewHiddenKeyPath = @"autoCompleteTableView.hidden";
static NSString *kBackgroundColorKeyPath = @"backgroundColor";
static NSString *kDefaultAutoCompleteCellIdentifier = @"_DefaultAutoCompleteCellIdentifier";
@interface MLPAutoCompleteTextField ()
@property (strong, readwrite) UITableView *autoCompleteTableView;
@property (strong) NSArray *autoCompleteSuggestions;
@property (strong) NSOperationQueue *autoCompleteSortQueue;
@property (strong) NSOperationQueue *autoCompleteFetchQueue;
@property (strong) NSString *reuseIdentifier;
@property (assign) CGColorRef originalShadowColor;
@property (assign) CGSize originalShadowOffset;
@property (assign) CGFloat originalShadowOpacity;
@end



@implementation MLPAutoCompleteTextField

#pragma mark - Init

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self initialize];
    }
    return self;
}


- (id)initWithCoder:(NSCoder *)coder
{
    self = [super initWithCoder:coder];
    if (self) {
        [self initialize];
    }
    return self;
}

- (void)dealloc
{
    [self closeAutoCompleteTableView];
    [self stopObservingKeyPathsAndNotifications];
}

- (void)initialize
{
    [self beginObservingKeyPathsAndNotifications];
    
    [self setDefaultValuesForVariables];
    
    UITableView *newTableView = [self newAutoCompleteTableViewForTextField:self];
    [self setAutoCompleteTableView:newTableView];
}

#pragma mark - Notifications and KVO

- (void)beginObservingKeyPathsAndNotifications
{
    [self addObserver:self
           forKeyPath:kBorderStyleKeyPath
              options:NSKeyValueObservingOptionNew context:nil];
    
    
    [self addObserver:self
           forKeyPath:kAutoCompleteTableViewHiddenKeyPath
              options:NSKeyValueObservingOptionNew context:nil];
    
    
    [self addObserver:self
           forKeyPath:kBackgroundColorKeyPath
              options:NSKeyValueObservingOptionNew context:nil];
    
    [self addObserver:self
           forKeyPath:kKeyboardAccessoryInputKeyPath
              options:NSKeyValueObservingOptionNew context:nil];
    
    
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(textFieldDidChangeWithNotification:)
                                                 name:UITextFieldTextDidChangeNotification object:self];
}

- (void)stopObservingKeyPathsAndNotifications
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    
    [self removeObserver:self forKeyPath:kBorderStyleKeyPath];
    [self removeObserver:self forKeyPath:kAutoCompleteTableViewHiddenKeyPath];
    [self removeObserver:self forKeyPath:kBackgroundColorKeyPath];
    [self removeObserver:self forKeyPath:kKeyboardAccessoryInputKeyPath];
}


- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if([keyPath isEqualToString:kBorderStyleKeyPath]) {
        //[self styleAutoCompleteTableForBorderStyle:self.borderStyle];
    } else if ([keyPath isEqualToString:kAutoCompleteTableViewHiddenKeyPath]) {
        if(self.autoCompleteTableView.hidden){
            [self closeAutoCompleteTableView];
        } else {
            [self.autoCompleteTableView reloadData];
        }
    } else if ([keyPath isEqualToString:kBackgroundColorKeyPath]){
        //[self styleAutoCompleteTableForBorderStyle:self.borderStyle];
    } else if ([keyPath isEqualToString:kKeyboardAccessoryInputKeyPath]){
        if(self.autoCompleteTableAppearsAsKeyboardAccessory){
            [self setAutoCompleteTableForKeyboardAppearance];
        } else {
            [self setAutoCompleteTableForDropDownAppearance];
        }
    }
}

#pragma mark - TableView Datasource

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    NSInteger numberOfRows = [self.autoCompleteSuggestions count];
    [self expandAutoCompleteTableViewForNumberOfRows:numberOfRows];
    return numberOfRows;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = nil;
    NSString *cellIdentifier = kDefaultAutoCompleteCellIdentifier;
    
    if(!self.reuseIdentifier){
        cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
        if (cell == nil) {
            cell = [self autoCompleteTableViewCellWithReuseIdentifier:cellIdentifier];
        }
    } else {
        cell = [tableView dequeueReusableCellWithIdentifier:self.reuseIdentifier];
    }
    NSAssert(cell, @"Unable to create cell for autocomplete table");
    
    
    id autoCompleteObject = self.autoCompleteSuggestions[indexPath.row];
    NSString *suggestedString;
    if([autoCompleteObject isKindOfClass:[NSString class]]){
        suggestedString = (NSString *)autoCompleteObject;
    } else if ([autoCompleteObject conformsToProtocol:@protocol(MLPAutoCompletionObject)]){
        suggestedString = [(id <MLPAutoCompletionObject>)autoCompleteObject autocompleteString];
    } else {
        NSAssert(0, @"Autocomplete suggestions must either be NSString or objects conforming to the MLPAutoCompletionObject protocol.");
    }
    
    
    [self configureCell:cell atIndexPath:indexPath withAutoCompleteString:suggestedString];
    
    
    return cell;
}

- (UITableViewCell *)autoCompleteTableViewCellWithReuseIdentifier:(NSString *)identifier
{
    UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
                                                   reuseIdentifier:identifier];
    [cell setBackgroundColor:[UIColor clearColor]];
    [cell.textLabel setTextColor:self.textColor];
    [cell.textLabel setFont:self.font];
    return cell;
}

+ (NSString *) accessibilityLabelForIndexPath:(NSIndexPath *)indexPath
{
    return [NSString stringWithFormat:@"{%ld,%ld}",(long)indexPath.section,(long)indexPath.row];
}

- (void)configureCell:(UITableViewCell *)cell
          atIndexPath:(NSIndexPath *)indexPath
withAutoCompleteString:(NSString *)string
{
    
    NSAttributedString *boldedString = nil;
    BOOL attributedTextSupport = [cell.textLabel respondsToSelector:@selector(setAttributedText:)];
    if(attributedTextSupport && self.applyBoldEffectToAutoCompleteSuggestions){
        NSRange boldedRange = [string rangeOfString:self.text options:NSCaseInsensitiveSearch | NSDiacriticInsensitiveSearch];
        boldedString = [self boldedString:string withRange:boldedRange];
    }
    
    id autoCompleteObject = self.autoCompleteSuggestions[indexPath.row];
    if(![autoCompleteObject conformsToProtocol:@protocol(MLPAutoCompletionObject)]){
        autoCompleteObject = nil;
    }
    
    if([self.autoCompleteDelegate respondsToSelector:@selector(autoCompleteTextField:shouldConfigureCell:withAutoCompleteString:withAttributedString:forAutoCompleteObject:forRowAtIndexPath:)])
    {
        if(![self.autoCompleteDelegate autoCompleteTextField:self shouldConfigureCell:cell withAutoCompleteString:string withAttributedString:boldedString forAutoCompleteObject:autoCompleteObject forRowAtIndexPath:indexPath])
        {
            return;
        }
    }
    
    [cell.textLabel setTextColor:self.textColor];
    
    if(boldedString){
        if ([cell.textLabel respondsToSelector:@selector(setAttributedText:)]) {
            [cell.textLabel setAttributedText:boldedString];
        } else{
            [cell.textLabel setText:string];
            [cell.textLabel setFont:[UIFont fontWithName:self.font.fontName size:self.autoCompleteFontSize]];
        }
        
    } else {
        [cell.textLabel setText:string];
        [cell.textLabel setFont:[UIFont fontWithName:self.font.fontName size:self.autoCompleteFontSize]];
    }
    
    cell.accessibilityLabel = [[self class] accessibilityLabelForIndexPath:indexPath];
    
    if(self.autoCompleteTableCellTextColor){
        [cell.textLabel setTextColor:self.autoCompleteTableCellTextColor];
    }
}

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    [cell setBackgroundColor:self.autoCompleteTableCellBackgroundColor];
}

#pragma mark - TableView Delegate

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return self.autoCompleteRowHeight;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if(!self.autoCompleteTableAppearsAsKeyboardAccessory){
        [self closeAutoCompleteTableView];
    }
    
    UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
    NSString *autoCompleteString = selectedCell.textLabel.text;
    self.text = autoCompleteString;
    
    id<MLPAutoCompletionObject> autoCompleteObject = self.autoCompleteSuggestions[indexPath.row];
    if(![autoCompleteObject conformsToProtocol:@protocol(MLPAutoCompletionObject)]){
        autoCompleteObject = nil;
    }
    
    if([self.autoCompleteDelegate respondsToSelector:
        @selector(autoCompleteTextField:didSelectAutoCompleteString:withAutoCompleteObject:forRowAtIndexPath:)]){
        
        [self.autoCompleteDelegate autoCompleteTextField:self
                             didSelectAutoCompleteString:autoCompleteString
                                  withAutoCompleteObject:autoCompleteObject
                                       forRowAtIndexPath:indexPath];
    }
    
    [self finishedSearching];
}

#pragma mark - AutoComplete Sort Operation Delegate


- (void)autoCompleteTermsDidSort:(NSArray *)completions
{
    [self setAutoCompleteSuggestions:completions];
    [self.autoCompleteTableView reloadData];
    
    if ([self.autoCompleteDelegate
         respondsToSelector:@selector(autoCompleteTextField:didChangeNumberOfSuggestions:)]) {
        [self.autoCompleteDelegate autoCompleteTextField:self
                            didChangeNumberOfSuggestions:self.autoCompleteSuggestions.count];
    }
}

- (NSInteger)maximumEditDistanceForAutoCompleteTerms
{
    return self.requireAutoCompleteSuggestionsToMatchInputExactly ? 0 : self.maximumEditDistance;
}

#pragma mark - AutoComplete Fetch Operation Delegate

- (void)autoCompleteTermsDidFetch:(NSDictionary *)fetchInfo
{
    NSString *inputString = fetchInfo[kFetchedStringKey];
    NSArray *completions = fetchInfo[kFetchedTermsKey];
    
    [self.autoCompleteSortQueue cancelAllOperations];
    
    if(self.sortAutoCompleteSuggestionsByClosestMatch){
        MLPAutoCompleteSortOperation *operation =
        [[MLPAutoCompleteSortOperation alloc] initWithDelegate:self
                                              incompleteString:inputString
                                           possibleCompletions:completions];
        [self.autoCompleteSortQueue addOperation:operation];
    } else {
        [self autoCompleteTermsDidSort:completions];
    }
}

#pragma mark - Events

- (void)textFieldDidChangeWithNotification:(NSNotification *)aNotification
{
    if(aNotification.object == self){
        [self reloadData];
    }
}

- (BOOL)becomeFirstResponder
{
    [self saveCurrentShadowProperties];
    
    if(self.showAutoCompleteTableWhenEditingBegins ||
       self.autoCompleteTableAppearsAsKeyboardAccessory){
        [self fetchAutoCompleteSuggestions];
    }
    
    return [super becomeFirstResponder];
}

- (void) finishedSearching
{
    if (self.shouldResignFirstResponderFromKeyboardAfterSelectionOfAutoCompleteRows) {
        [self resignFirstResponder];
    }
}

- (BOOL)resignFirstResponder
{
    [self restoreOriginalShadowProperties];
    if(!self.autoCompleteTableAppearsAsKeyboardAccessory){
        [self closeAutoCompleteTableView];
    }
    return [super resignFirstResponder];
}



#pragma mark - Open/Close Actions

- (void)expandAutoCompleteTableViewForNumberOfRows:(NSInteger)numberOfRows
{
    NSAssert(numberOfRows >= 0,
             @"Number of rows given for auto complete table was negative, this is impossible.");
    
    if(!self.isFirstResponder){
        return;
    }
    
    if(self.autoCompleteTableAppearsAsKeyboardAccessory){
        [self expandKeyboardAutoCompleteTableForNumberOfRows:numberOfRows];
    } else {
        [self expandDropDownAutoCompleteTableForNumberOfRows:numberOfRows];
    }
    
}

- (void)expandKeyboardAutoCompleteTableForNumberOfRows:(NSInteger)numberOfRows
{
    if(numberOfRows && (self.autoCompleteTableViewHidden == NO)){
        [self.autoCompleteTableView setAlpha:1];
    } else {
        [self.autoCompleteTableView setAlpha:0];
    }
}

- (void)expandDropDownAutoCompleteTableForNumberOfRows:(NSInteger)numberOfRows
{
    [self resetDropDownAutoCompleteTableFrameForNumberOfRows:numberOfRows];
    
    
    if(numberOfRows && (self.autoCompleteTableViewHidden == NO)){
        [self.autoCompleteTableView setAlpha:1];
        
        BOOL tableViewWillBeAddedToViewHierarchy = !self.autoCompleteTableView.superview;
        if(tableViewWillBeAddedToViewHierarchy){
            if([self.autoCompleteDelegate
                respondsToSelector:@selector(autoCompleteTextField:willShowAutoCompleteTableView:)]){
                [self.autoCompleteDelegate autoCompleteTextField:self
                                   willShowAutoCompleteTableView:self.autoCompleteTableView];
            }
        }
        
        [self.superview bringSubviewToFront:self];
#if BROKEN
        UIView *rootView = [self.window.subviews objectAtIndex:0];
        [rootView insertSubview:self.autoCompleteTableView
                   belowSubview:self];
#else
        [self.superview insertSubview:self.autoCompleteTableView
                         belowSubview:self];
#endif
        [self.autoCompleteTableView setUserInteractionEnabled:YES];
        if(self.showTextFieldDropShadowWhenAutoCompleteTableIsOpen){
            [self.layer setShadowColor:[[UIColor blackColor] CGColor]];
            [self.layer setShadowOffset:CGSizeMake(0, 1)];
            [self.layer setShadowOpacity:0.35];
        }
        
        if (tableViewWillBeAddedToViewHierarchy && [self.autoCompleteDelegate respondsToSelector:@selector(autoCompleteTextField:didShowAutoCompleteTableView:)]) {
            [self.autoCompleteDelegate autoCompleteTextField:self
                                didShowAutoCompleteTableView:self.autoCompleteTableView];
        }
    } else {
        [self closeAutoCompleteTableView];
        [self restoreOriginalShadowProperties];
        [self.autoCompleteTableView.layer setShadowOpacity:0.0];
    }
}


- (void)closeAutoCompleteTableView
{
    if ([self.autoCompleteDelegate respondsToSelector:@selector(autoCompleteTextField:willHideAutoCompleteTableView:)]) {
        [self.autoCompleteDelegate autoCompleteTextField:self
                           willHideAutoCompleteTableView:self.autoCompleteTableView];
    }
    [self.autoCompleteTableView removeFromSuperview];
    [self restoreOriginalShadowProperties];
    if ([self.autoCompleteDelegate respondsToSelector:@selector(autoCompleteTextField:didHideAutoCompleteTableView:)]) {
        [self.autoCompleteDelegate autoCompleteTextField:self
                            didHideAutoCompleteTableView:self.autoCompleteTableView];
    }
}


#pragma mark - Setters



- (void)setDefaultValuesForVariables
{
    [self setClipsToBounds:NO];
    [self setAutoCompleteFetchRequestDelay:DefaultAutoCompleteRequestDelay];
    [self setSortAutoCompleteSuggestionsByClosestMatch:YES];
    [self setApplyBoldEffectToAutoCompleteSuggestions:YES];
    [self setShowTextFieldDropShadowWhenAutoCompleteTableIsOpen:YES];
    [self setShouldResignFirstResponderFromKeyboardAfterSelectionOfAutoCompleteRows:YES];
    [self setAutoCompleteRowHeight:40];
    [self setAutoCompleteFontSize:13];
    [self setMaximumNumberOfAutoCompleteRows:3];
    [self setPartOfAutoCompleteRowHeightToCut:0.5f];
    
    [self setMaximumEditDistance:100];
    [self setRequireAutoCompleteSuggestionsToMatchInputExactly:NO];
    
    [self setAutoCompleteTableCellBackgroundColor:[UIColor clearColor]];
    
    UIFont *regularFont = [UIFont systemFontOfSize:13];
    [self setAutoCompleteRegularFontName:regularFont.fontName];
    
    UIFont *boldFont = [UIFont boldSystemFontOfSize:13];
    [self setAutoCompleteBoldFontName:boldFont.fontName];
    
    [self setAutoCompleteSuggestions:[NSMutableArray array]];
    
    [self setAutoCompleteSortQueue:[NSOperationQueue new]];
    self.autoCompleteSortQueue.name = [NSString stringWithFormat:@"Autocomplete Queue %i", arc4random()];
    
    [self setAutoCompleteFetchQueue:[NSOperationQueue new]];
    self.autoCompleteFetchQueue.name = [NSString stringWithFormat:@"Fetch Queue %i", arc4random()];
}


- (void)setAutoCompleteTableForKeyboardAppearance
{
    [self resetKeyboardAutoCompleteTableFrameForNumberOfRows:self.maximumNumberOfAutoCompleteRows];
    [self.autoCompleteTableView setContentInset:UIEdgeInsetsZero];
    [self.autoCompleteTableView setScrollIndicatorInsets:UIEdgeInsetsZero];
    [self setInputAccessoryView:self.autoCompleteTableView];
}

- (void)setAutoCompleteTableForDropDownAppearance
{
    [self resetDropDownAutoCompleteTableFrameForNumberOfRows:self.maximumNumberOfAutoCompleteRows];
    [self.autoCompleteTableView setContentInset:self.autoCompleteContentInsets];
    [self.autoCompleteTableView setScrollIndicatorInsets:self.autoCompleteScrollIndicatorInsets];
    [self setInputAccessoryView:nil];
}



- (void)setAutoCompleteTableViewHidden:(BOOL)autoCompleteTableViewHidden
{
    [self.autoCompleteTableView setHidden:autoCompleteTableViewHidden];
}

- (void)setAutoCompleteTableBackgroundColor:(UIColor *)autoCompleteTableBackgroundColor
{
    [self.autoCompleteTableView setBackgroundColor:autoCompleteTableBackgroundColor];
    _autoCompleteTableBackgroundColor = autoCompleteTableBackgroundColor;
}

- (void)setAutoCompleteTableBorderWidth:(CGFloat)autoCompleteTableBorderWidth
{
    [self.autoCompleteTableView.layer setBorderWidth:autoCompleteTableBorderWidth];
    _autoCompleteTableBorderWidth = autoCompleteTableBorderWidth;
}

- (void)setAutoCompleteTableBorderColor:(UIColor *)autoCompleteTableBorderColor
{
    [self.autoCompleteTableView.layer setBorderColor:[autoCompleteTableBorderColor CGColor]];
    _autoCompleteTableBorderColor = autoCompleteTableBorderColor;
}

- (void)setAutoCompleteContentInsets:(UIEdgeInsets)autoCompleteContentInsets
{
    [self.autoCompleteTableView setContentInset:autoCompleteContentInsets];
    _autoCompleteContentInsets = autoCompleteContentInsets;
}

- (void)setAutoCompleteScrollIndicatorInsets:(UIEdgeInsets)autoCompleteScrollIndicatorInsets
{
    [self.autoCompleteTableView setScrollIndicatorInsets:autoCompleteScrollIndicatorInsets];
    _autoCompleteScrollIndicatorInsets = autoCompleteScrollIndicatorInsets;
}

- (void)resetKeyboardAutoCompleteTableFrameForNumberOfRows:(NSInteger)numberOfRows
{
    [self.autoCompleteTableView.layer setCornerRadius:0];
    
    CGRect newAutoCompleteTableViewFrame = [self autoCompleteTableViewFrameForTextField:self forNumberOfRows:numberOfRows];
    [self.autoCompleteTableView setFrame:newAutoCompleteTableViewFrame];
    
    [self.autoCompleteTableView setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
    [self.autoCompleteTableView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO];
}

- (void)resetDropDownAutoCompleteTableFrameForNumberOfRows:(NSInteger)numberOfRows
{
    [self.autoCompleteTableView.layer setCornerRadius:self.autoCompleteTableCornerRadius];
    
    CGRect newAutoCompleteTableViewFrame = [self autoCompleteTableViewFrameForTextField:self forNumberOfRows:numberOfRows];
    
    [self.autoCompleteTableView setFrame:newAutoCompleteTableViewFrame];
    [self.autoCompleteTableView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO];
}

- (void)registerAutoCompleteCellNib:(UINib *)nib forCellReuseIdentifier:(NSString *)reuseIdentifier
{
    NSAssert(self.autoCompleteTableView, @"Must have an autoCompleteTableView to register cells to.");
    
    if(self.reuseIdentifier){
        [self unregisterAutoCompleteCellForReuseIdentifier:self.reuseIdentifier];
    }
    
    [self.autoCompleteTableView registerNib:nib forCellReuseIdentifier:reuseIdentifier];
    [self setReuseIdentifier:reuseIdentifier];
}


- (void)registerAutoCompleteCellClass:(Class)cellClass forCellReuseIdentifier:(NSString *)reuseIdentifier
{
    NSAssert(self.autoCompleteTableView, @"Must have an autoCompleteTableView to register cells to.");
    if(self.reuseIdentifier){
        [self unregisterAutoCompleteCellForReuseIdentifier:self.reuseIdentifier];
    }
    
    BOOL classSettingSupported = NO;
    classSettingSupported = [self.autoCompleteTableView respondsToSelector:@selector(registerClass:forCellReuseIdentifier:)];
    
    NSAssert(classSettingSupported, @"Unable to set class for cell for autocomplete table, in iOS 5.0 you can set a custom NIB for a reuse identifier to get similar functionality.");
    [self.autoCompleteTableView registerClass:cellClass forCellReuseIdentifier:reuseIdentifier];
    [self setReuseIdentifier:reuseIdentifier];
}


- (void)unregisterAutoCompleteCellForReuseIdentifier:(NSString *)reuseIdentifier
{
    [self.autoCompleteTableView registerNib:nil forCellReuseIdentifier:reuseIdentifier];
}


- (void)styleAutoCompleteTableForBorderStyle:(UITextBorderStyle)borderStyle
{
    if([self.autoCompleteDelegate respondsToSelector:@selector(autoCompleteTextField:shouldStyleAutoCompleteTableView:forBorderStyle:)]){
        if(![self.autoCompleteDelegate autoCompleteTextField:self
                            shouldStyleAutoCompleteTableView:self.autoCompleteTableView
                                              forBorderStyle:borderStyle]){
            return;
        }
    }
    
    switch (borderStyle) {
        case UITextBorderStyleRoundedRect:
            [self setRoundedRectStyleForAutoCompleteTableView];
            break;
        case UITextBorderStyleBezel:
        case UITextBorderStyleLine:
            [self setLineStyleForAutoCompleteTableView];
            break;
        case UITextBorderStyleNone:
            [self setNoneStyleForAutoCompleteTableView];
            break;
        default:
            break;
    }
}



- (void)setRoundedRectStyleForAutoCompleteTableView
{
    [self setAutoCompleteTableCornerRadius:8.0];
    [self setAutoCompleteTableOriginOffset:CGSizeMake(0, -18)];
    [self setAutoCompleteScrollIndicatorInsets:UIEdgeInsetsMake(18, 0, 0, 0)];
    [self setAutoCompleteContentInsets:UIEdgeInsetsMake(18, 0, 0, 0)];
    
    if(self.backgroundColor == [UIColor clearColor]){
        [self setAutoCompleteTableBackgroundColor:[UIColor whiteColor]];
    } else {
        [self setAutoCompleteTableBackgroundColor:self.backgroundColor];
    }
}

- (void)setLineStyleForAutoCompleteTableView
{
    [self setAutoCompleteTableCornerRadius:0.0];
    [self setAutoCompleteTableOriginOffset:CGSizeZero];
    [self setAutoCompleteScrollIndicatorInsets:UIEdgeInsetsZero];
    [self setAutoCompleteContentInsets:UIEdgeInsetsZero];
    [self setAutoCompleteTableBorderWidth:1.0];
    [self setAutoCompleteTableBorderColor:[UIColor colorWithWhite:0.0 alpha:0.5]];
    
    if(self.backgroundColor == [UIColor clearColor]){
        [self setAutoCompleteTableBackgroundColor:[UIColor whiteColor]];
    } else {
        [self setAutoCompleteTableBackgroundColor:self.backgroundColor];
    }
}

- (void)setNoneStyleForAutoCompleteTableView
{
    [self setAutoCompleteTableCornerRadius:8.0];
    [self setAutoCompleteTableOriginOffset:CGSizeMake(0, 7)];
    [self setAutoCompleteScrollIndicatorInsets:UIEdgeInsetsZero];
    [self setAutoCompleteContentInsets:UIEdgeInsetsZero];
    [self setAutoCompleteTableBorderWidth:1.0];
    
    
    UIColor *lightBlueColor = [UIColor colorWithRed:181/255.0
                                              green:204/255.0
                                               blue:255/255.0
                                              alpha:1.0];
    [self setAutoCompleteTableBorderColor:lightBlueColor];
    
    
    UIColor *blueTextColor = [UIColor colorWithRed:23/255.0
                                             green:119/255.0
                                              blue:206/255.0
                                             alpha:1.0];
    [self setAutoCompleteTableCellTextColor:blueTextColor];
    
    if(self.backgroundColor == [UIColor clearColor]){
        [self setAutoCompleteTableBackgroundColor:[UIColor whiteColor]];
    } else {
        [self setAutoCompleteTableBackgroundColor:self.backgroundColor];
    }
}

- (void)saveCurrentShadowProperties
{
    [self setOriginalShadowColor:self.layer.shadowColor];
    [self setOriginalShadowOffset:self.layer.shadowOffset];
    [self setOriginalShadowOpacity:self.layer.shadowOpacity];
}

- (void)restoreOriginalShadowProperties
{
    [self.layer setShadowColor:self.originalShadowColor];
    [self.layer setShadowOffset:self.originalShadowOffset];
    [self.layer setShadowOpacity:self.originalShadowOpacity];
}

- (void)reloadData {
    [NSObject cancelPreviousPerformRequestsWithTarget:self
                                             selector:@selector(fetchAutoCompleteSuggestions)
                                               object:nil];
    
    [self performSelector:@selector(fetchAutoCompleteSuggestions)
               withObject:nil
               afterDelay:self.autoCompleteFetchRequestDelay];
}

#pragma mark - Getters

- (BOOL)autoCompleteTableViewHidden
{
    return self.autoCompleteTableView.hidden;
}


- (void)fetchAutoCompleteSuggestions
{
    
    if(self.disableAutoCompleteTableUserInteractionWhileFetching){
        [self.autoCompleteTableView setUserInteractionEnabled:NO];
    }
    
    [self.autoCompleteFetchQueue cancelAllOperations];
    
    MLPAutoCompleteFetchOperation *fetchOperation = [[MLPAutoCompleteFetchOperation alloc]
                                                     initWithDelegate:self
                                                     completionsDataSource:self.autoCompleteDataSource
                                                     autoCompleteTextField:self];
    
    [self.autoCompleteFetchQueue addOperation:fetchOperation];
}



#pragma mark - Factory Methods

- (UITableView *)newAutoCompleteTableViewForTextField:(MLPAutoCompleteTextField *)textField
{
    CGRect dropDownTableFrame = [self autoCompleteTableViewFrameForTextField:textField];
    
    UITableView *newTableView = [[UITableView alloc] initWithFrame:dropDownTableFrame
                                                             style:UITableViewStylePlain];
    [newTableView setDelegate:textField];
    [newTableView setDataSource:textField];
    [newTableView setScrollEnabled:YES];
    [newTableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
    
    return newTableView;
}

- (CGRect)autoCompleteTableViewFrameForTextField:(MLPAutoCompleteTextField *)textField
                                 forNumberOfRows:(NSInteger)numberOfRows
{
#if BROKEN
    // TODO: Reimplement this code for people using table views. Right now it breaks
    //       more normal use cases because of UILayoutContainerView
    CGRect newTableViewFrame             = [self autoCompleteTableViewFrameForTextField:textField];
    
    UIView *rootView                     = [textField.window.subviews objectAtIndex:0];
    CGRect textFieldFrameInContainerView = [rootView convertRect:textField.bounds
                                                        fromView:textField];
    
    CGFloat textfieldTopInset = textField.autoCompleteTableView.contentInset.top;
    CGFloat converted_originY = textFieldFrameInContainerView.origin.y + textfieldTopInset;
    
#else
    CGRect newTableViewFrame = [self autoCompleteTableViewFrameForTextField:textField];
    CGFloat textfieldTopInset = textField.autoCompleteTableView.contentInset.top;
#endif
    
    CGFloat height = [self autoCompleteTableHeightForTextField:textField withNumberOfRows:numberOfRows];
    
    newTableViewFrame.size.height = height;
#if BROKEN
    newTableViewFrame.origin.y    = converted_originY;
#endif
    
    if(!textField.autoCompleteTableAppearsAsKeyboardAccessory){
        newTableViewFrame.size.height += textfieldTopInset;
    }
    
    return newTableViewFrame;
}

- (CGFloat)autoCompleteTableHeightForTextField:(MLPAutoCompleteTextField *)textField
                              withNumberOfRows:(NSInteger)numberOfRows
{
    CGFloat maximumHeightMultiplier = (textField.maximumNumberOfAutoCompleteRows - textField.partOfAutoCompleteRowHeightToCut);
    CGFloat heightMultiplier;
    if(numberOfRows >= textField.maximumNumberOfAutoCompleteRows){
        heightMultiplier = maximumHeightMultiplier;
    } else {
        heightMultiplier = numberOfRows;
    }
    
    CGFloat height = textField.autoCompleteRowHeight * heightMultiplier;
    return height;
}

- (CGRect)autoCompleteTableViewFrameForTextField:(MLPAutoCompleteTextField *)textField
{
    CGRect frame = CGRectZero;
    
    if (CGRectGetWidth(self.autoCompleteTableFrame) > 0){
        frame = self.autoCompleteTableFrame;
    } else {
        frame = textField.frame;
        frame.origin.y += textField.frame.size.height;
    }
    
    frame.origin.x += textField.autoCompleteTableOriginOffset.width;
    frame.origin.y += textField.autoCompleteTableOriginOffset.height;
    frame.size.height += textField.autoCompleteTableSizeOffset.height;
    frame.size.width += textField.autoCompleteTableSizeOffset.width;
    frame = CGRectInset(frame, 1, 0);
    
    return frame;
}

- (NSAttributedString *)boldedString:(NSString *)string withRange:(NSRange)boldRange
{
    UIFont *boldFont = [UIFont fontWithName:self.autoCompleteBoldFontName
                                       size:self.autoCompleteFontSize];
    UIFont *regularFont = [UIFont fontWithName:self.autoCompleteRegularFontName
                                          size:self.autoCompleteFontSize];
    
    NSDictionary *boldTextAttributes = @{NSFontAttributeName : boldFont};
    NSDictionary *regularTextAttributes = @{NSFontAttributeName : regularFont};
    NSDictionary *firstAttributes;
    NSDictionary *secondAttributes;
    
    if(self.reverseAutoCompleteSuggestionsBoldEffect){
        firstAttributes = regularTextAttributes;
        secondAttributes = boldTextAttributes;
    } else {
        firstAttributes = boldTextAttributes;
        secondAttributes = regularTextAttributes;
    }
    
    NSMutableAttributedString *attributedText =
    [[NSMutableAttributedString alloc] initWithString:string
                                           attributes:firstAttributes];
    [attributedText setAttributes:secondAttributes range:boldRange];
    
    return attributedText;
}


@end







#pragma mark -
#pragma mark - MLPAutoCompleteFetchOperation
@implementation MLPAutoCompleteFetchOperation{
    dispatch_semaphore_t sentinelSemaphore;
}

- (void) cancel
{
    if (sentinelSemaphore) dispatch_semaphore_signal(sentinelSemaphore);
    [super cancel];
}

- (void)main
{
    @autoreleasepool {
        
        if (self.isCancelled){
            return;
        }
        
        
        if([self.dataSource respondsToSelector:@selector(autoCompleteTextField:possibleCompletionsForString:completionHandler:)]){
            __weak MLPAutoCompleteFetchOperation *operation = self;
            sentinelSemaphore = dispatch_semaphore_create(0);
            [self.dataSource autoCompleteTextField:self.textField
                      possibleCompletionsForString:self.incompleteString
                                 completionHandler:^(NSArray *suggestions){
                                     
                                     [operation performSelector:@selector(didReceiveSuggestions:) withObject:suggestions];
                                     dispatch_semaphore_signal(sentinelSemaphore);
                                 }];
            
            dispatch_semaphore_wait(sentinelSemaphore, DISPATCH_TIME_FOREVER);
            if(self.isCancelled){
                return;
            }
        } else if ([self.dataSource respondsToSelector:@selector(autoCompleteTextField:possibleCompletionsForString:)]){
            
            NSArray *results = [self.dataSource autoCompleteTextField:self.textField
                                         possibleCompletionsForString:self.incompleteString];
            
            if(!self.isCancelled){
                [self didReceiveSuggestions:results];
            }
            
        } else {
            NSAssert(0, @"An autocomplete datasource must implement either autoCompleteTextField:possibleCompletionsForString: or autoCompleteTextField:possibleCompletionsForString:completionHandler:");
        }
        
    }
}

- (void)didReceiveSuggestions:(NSArray *)suggestions
{
    if(suggestions == nil){
        suggestions = [NSArray array];
    }
    
    if(!self.isCancelled){
        
        if(suggestions.count){
            
            NSObject *firstObject = nil;
            firstObject = suggestions[0];
            
            NSAssert([firstObject isKindOfClass:[NSString class]] ||
                     [firstObject conformsToProtocol:@protocol(MLPAutoCompletionObject)],
                     @"MLPAutoCompleteTextField expects an array with objects that are either strings or conform to the MLPAutoCompletionObject protocol for possible completions.");
        }
        
        NSDictionary *resultsInfo = @{kFetchedTermsKey: suggestions,
                                      kFetchedStringKey : self.incompleteString};
        [(NSObject *)self.delegate
         performSelectorOnMainThread:@selector(autoCompleteTermsDidFetch:)
         withObject:resultsInfo
         waitUntilDone:NO];
    };
}

- (id)initWithDelegate:(id<MLPAutoCompleteFetchOperationDelegate>)aDelegate
 completionsDataSource:(id<MLPAutoCompleteTextFieldDataSource>)aDataSource
 autoCompleteTextField:(MLPAutoCompleteTextField *)aTextField
{
    self = [super init];
    if (self) {
        [self setDelegate:aDelegate];
        [self setTextField:aTextField];
        [self setDataSource:aDataSource];
        [self setIncompleteString:aTextField.text];
        
        if(!self.incompleteString){
            self.incompleteString = @"";
        }
    }
    return self;
}

- (void)dealloc
{
    [self setDelegate:nil];
    [self setTextField:nil];
    [self setDataSource:nil];
    [self setIncompleteString:nil];
}
@end





#pragma mark -
#pragma mark - MLPAutoCompleteSortOperation

@implementation MLPAutoCompleteSortOperation

- (void)main
{
    @autoreleasepool {
        
        if (self.isCancelled){
            return;
        }
        
        NSArray *results = [self sortedCompletionsForString:self.incompleteString
                                        withPossibleStrings:self.possibleCompletions];
        
        if (self.isCancelled){
            return;
        }
        
        if(!self.isCancelled){
            [(NSObject *)self.delegate
             performSelectorOnMainThread:@selector(autoCompleteTermsDidSort:)
             withObject:results
             waitUntilDone:NO];
        }
    }
}

- (id)initWithDelegate:(id<MLPAutoCompleteSortOperationDelegate>)aDelegate
      incompleteString:(NSString *)string
   possibleCompletions:(NSArray *)possibleStrings
{
    self = [super init];
    if (self) {
        [self setDelegate:aDelegate];
        [self setIncompleteString:string];
        [self setPossibleCompletions:possibleStrings];
    }
    return self;
}

- (NSArray *)sortedCompletionsForString:(NSString *)inputString withPossibleStrings:(NSArray *)possibleTerms
{
    if([inputString isEqualToString:@""]){
        return possibleTerms;
    }
    
    if(self.isCancelled){
        return [NSArray array];
    }
    
    NSMutableArray *editDistances = [NSMutableArray arrayWithCapacity:possibleTerms.count];
    
    NSInteger maxEditDistance = self.delegate.maximumEditDistanceForAutoCompleteTerms;
    
    for(NSObject *originalObject in possibleTerms) {
        
        NSString *currentString;
        if([originalObject isKindOfClass:[NSString class]]){
            currentString = (NSString *)originalObject;
        } else if ([originalObject conformsToProtocol:@protocol(MLPAutoCompletionObject)]){
            currentString = [(id <MLPAutoCompletionObject>)originalObject autocompleteString];
        } else {
            NSAssert(0, @"Autocompletion terms must either be strings or objects conforming to the MLPAutoCompleteObject protocol.");
        }
        
        if(self.isCancelled){
            return [NSArray array];
        }
        
        NSUInteger maximumRange = (inputString.length < currentString.length) ? inputString.length : currentString.length;
        float editDistanceOfCurrentString = [inputString asciiLevenshteinDistanceWithString:[currentString substringWithRange:NSMakeRange(0, maximumRange)]];
        
        if(editDistanceOfCurrentString > maxEditDistance){
            continue;
        }
        
        NSDictionary * stringsWithEditDistances = @{kSortInputStringKey : currentString ,
                                                    kSortObjectKey : originalObject,
                                                    kSortEditDistancesKey : [NSNumber numberWithFloat:editDistanceOfCurrentString]};
        [editDistances addObject:stringsWithEditDistances];
    }
    
    if(self.isCancelled){
        return [NSArray array];
    }
    
    [editDistances sortUsingComparator:^(NSDictionary *string1Dictionary,
                                         NSDictionary *string2Dictionary){
        
        return [string1Dictionary[kSortEditDistancesKey]
                compare:string2Dictionary[kSortEditDistancesKey]];
        
    }];
    
    
    
    NSMutableArray *prioritySuggestions = [NSMutableArray array];
    NSMutableArray *otherSuggestions = [NSMutableArray array];
    for(NSDictionary *stringsWithEditDistances in editDistances){
        
        if(self.isCancelled){
            return [NSArray array];
        }
        
        NSObject *autoCompleteObject = stringsWithEditDistances[kSortObjectKey];
        NSString *suggestedString = stringsWithEditDistances[kSortInputStringKey];
        
        NSArray *suggestedStringComponents = [suggestedString componentsSeparatedByString:@" "];
        BOOL suggestedStringDeservesPriority = NO;
        for(NSString *component in suggestedStringComponents){
            NSRange occurrenceOfInputString = [[component lowercaseString]
                                               rangeOfString:[inputString lowercaseString]];
            
            if (occurrenceOfInputString.length != 0 && occurrenceOfInputString.location == 0) {
                suggestedStringDeservesPriority = YES;
                [prioritySuggestions addObject:autoCompleteObject];
                break;
            }
            
            if([inputString length] <= 1){
                //if the input string is very short, don't check anymore components of the input string.
                break;
            }
        }
        
        if(!suggestedStringDeservesPriority){
            [otherSuggestions addObject:autoCompleteObject];
        }
        
    }
    
    NSMutableArray *results = [NSMutableArray array];
    [results addObjectsFromArray:prioritySuggestions];
    [results addObjectsFromArray:otherSuggestions];
    
    
    return [NSArray arrayWithArray:results];
}

- (void)dealloc
{
    [self setDelegate:nil];
    [self setIncompleteString:nil];
    [self setPossibleCompletions:nil];
}
@end


================================================
FILE: MLPAutoCompleteTextField/MLPAutoCompleteTextFieldDataSource.h
================================================
/*
 //  MLPAutoCompleteTextFieldDataSource.h
 //
 //
 //  Created by Eddy Borja on 12/29/12.
 //  Copyright (c) 2013 Mainloop LLC. All rights reserved.
 
 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 
 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#import <Foundation/Foundation.h>

@class MLPAutoCompleteTextField;
@protocol MLPAutoCompleteTextFieldDataSource <NSObject>


@optional
//One of these two methods must be implemented to fetch autocomplete terms.


/*
 When you have the suggestions ready you must call the completionHandler block with
 an NSArray of strings or objects implementing the MLPAutoCompletionObject protocol that
 could be used as possible completions for the given string in textField.
 */
- (void)autoCompleteTextField:(MLPAutoCompleteTextField *)textField
 possibleCompletionsForString:(NSString *)string
            completionHandler:(void(^)(NSArray *suggestions))handler;



/*
 Like the above, this method should return an NSArray of strings or objects implementing the MLPAutoCompletionObject protocol
 that could be used as possible completions for the given string in textField.
 This method will be called asynchronously, so an immediate return is not necessary.
 */
- (NSArray *)autoCompleteTextField:(MLPAutoCompleteTextField *)textField
      possibleCompletionsForString:(NSString *)string;



@end


================================================
FILE: MLPAutoCompleteTextField/MLPAutoCompleteTextFieldDelegate.h
================================================
/*
 //  MLPAutoCompleteTextFieldDelegate.h
 //
 //
 //  Created by Eddy Borja on 2/5/13.
 //  Copyright (c) 2013 Mainloop LLC. All rights reserved.
 
 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 
 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#import <Foundation/Foundation.h>
#import "MLPAutoCompletionObject.h"

@class MLPAutoCompleteTextField;
@protocol MLPAutoCompleteTextFieldDelegate <NSObject>

@optional
- (BOOL)autoCompleteTextField:(MLPAutoCompleteTextField *)textField
shouldStyleAutoCompleteTableView:(UITableView *)autoCompleteTableView
               forBorderStyle:(UITextBorderStyle)borderStyle;

/*IndexPath corresponds to the order of strings within the autocomplete table,
 not the original data source.*/
- (BOOL)autoCompleteTextField:(MLPAutoCompleteTextField *)textField
          shouldConfigureCell:(UITableViewCell *)cell
       withAutoCompleteString:(NSString *)autocompleteString
         withAttributedString:(NSAttributedString *)boldedString
        forAutoCompleteObject:(id<MLPAutoCompletionObject>)autocompleteObject
            forRowAtIndexPath:(NSIndexPath *)indexPath;


/*IndexPath corresponds to the order of strings within the autocomplete table,
 not the original data source.
 autoCompleteObject may be nil if the selectedString had no object associated with it.
 */
- (void)autoCompleteTextField:(MLPAutoCompleteTextField *)textField
  didSelectAutoCompleteString:(NSString *)selectedString
       withAutoCompleteObject:(id<MLPAutoCompletionObject>)selectedObject
            forRowAtIndexPath:(NSIndexPath *)indexPath;


- (void)autoCompleteTextField:(MLPAutoCompleteTextField *)textField
willShowAutoCompleteTableView:(UITableView *)autoCompleteTableView;

- (void)autoCompleteTextField:(MLPAutoCompleteTextField *)textField
 didShowAutoCompleteTableView:(UITableView *)autoCompleteTableView;

- (void)autoCompleteTextField:(MLPAutoCompleteTextField *)textField
willHideAutoCompleteTableView:(UITableView *)autoCompleteTableView;

- (void)autoCompleteTextField:(MLPAutoCompleteTextField *)textField
 didHideAutoCompleteTableView:(UITableView *)autoCompleteTableView;

- (void)autoCompleteTextField:(MLPAutoCompleteTextField *)textField
 didChangeNumberOfSuggestions:(NSInteger)numberOfSuggestions;

@end


================================================
FILE: MLPAutoCompleteTextField/MLPAutoCompletionObject.h
================================================
/*
 //  MLPAutoCompletionObject.h
 //
 //
 //  Created by Eddy Borja on 4/19/13.
 //  Copyright (c) 2013 Mainloop LLC. All rights reserved.
 //
 
 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 
 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */


#import <Foundation/Foundation.h>

/*
 In some cases you may want strings in an autocomplete menu to be associated to some kind of model object
 (For example: a list of names may be
 associated with friend objects and you want to track which friend object a
 user selects based on what name they choose from the autocomplete list.)
 
 In order to pass your model objects straight to the MLPAutoCompleteTextFieldDataSource's
 autoCompleteTextField:possibleCompletionsForString: method, your model object must implement this protocol.
 */
@protocol MLPAutoCompletionObject <NSObject>
@required

/*Return the string that should be displayed in the autocomplete menu that
 represents this object. (For example: a person's name.)*/
- (NSString *)autocompleteString;

@end


================================================
FILE: MLPAutoCompleteTextField/NSString+Levenshtein.h
================================================
//
//  NSString+Levenshtein.h
//
//  Created by Mark Aufflick on 9/11/09.
//  Copyright 2009 pumptheory.com. All rights reserved.
//
//  Based loosely on the NSString(Levenshtein) code by Rick Bourner
//  rick@bourner.com <http://www.merriampark.com/ldobjc.htm>
//

/*
 
 Copyright (c) 2009, Mark Aufflick
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
 
 * Redistributions of source code must retain the above copyright
 notice, this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 notice, this list of conditions and the following disclaimer in the
 documentation and/or other materials provided with the distribution.
 * Neither the name of the Mark Aufflick nor the
 names of contributors may be used to endorse or promote products
 derived from this software without specific prior written permission.
 
 THIS SOFTWARE IS PROVIDED BY MARK AUFFLICK ''AS IS'' AND ANY
 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL MARK AUFFLICK BE LIABLE FOR ANY
 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 */


#import <Foundation/Foundation.h>
#import <float.h>

// used to indicate that stringB is nil
#define LEV_INF_DISTANCE FLT_MAX

@interface NSString(Levenshtein)

- (float) asciiLevenshteinDistanceWithString: (NSString *)stringB;
- (float) asciiLevenshteinDistanceWithString: (NSString *)stringB skippingCharacterSet: (NSCharacterSet *)charset;

@end

================================================
FILE: MLPAutoCompleteTextField/NSString+Levenshtein.m
================================================
//
//  NSString+Levenshtein.m
//
//  Created by Mark Aufflick on 9/11/09.
//  mark@aufflick.com <http://mark.aufflick.com/>
//
//  Based somewhat on the NSString(Levenshtein) code by Rick Bourner
//  rick@bourner.com <http://www.merriampark.com/ldobjc.htm>
//  which in turn implements a variation on the Wagner-Fischer algorithm
//

/*
 
 Copyright (c) 2009, Mark Aufflick
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
 
 * Redistributions of source code must retain the above copyright
 notice, this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 notice, this list of conditions and the following disclaimer in the
 documentation and/or other materials provided with the distribution.
 * Neither the name of the Mark Aufflick nor the
 names of contributors may be used to endorse or promote products
 derived from this software without specific prior written permission.
 
 THIS SOFTWARE IS PROVIDED BY MARK AUFFLICK ''AS IS'' AND ANY
 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL MARK AUFFLICK BE LIABLE FOR ANY
 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 */

#import "NSString+Levenshtein.h"

// private util function
int smallestOf(int a, int b, int c);

@implementation NSString (Levenshtein)

- (float) asciiLevenshteinDistanceWithString: (NSString *)stringB
{
    return [self asciiLevenshteinDistanceWithString:stringB
                               skippingCharacterSet:nil];
}


- (float) asciiLevenshteinDistanceWithString: (NSString *)stringB skippingCharacterSet: (NSCharacterSet *)charset
{
    // try to convince caller that a nil object is *really* different from any string
    if (!stringB)
        return LEV_INF_DISTANCE;
    
    // strip chars from the requested charset (if any)
    
    NSString *stringA;
    if (charset) {
        stringA = [[self componentsSeparatedByCharactersInSet:charset] componentsJoinedByString:@""];
        stringB = [[stringB componentsSeparatedByCharactersInSet:charset] componentsJoinedByString:@""];
    } else {
        stringA = self;
    }
    
    // converting to ASCII to normalize characters with accents etc.
    // and also so we can use treat the string as an array of char *
    
    NSData *dataA = [stringA dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
    NSData *dataB = [stringB dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
    
    // not really cstrings, since not nul terminated
    const char *cstringA = [dataA bytes];
    const char *cstringB = [dataB bytes];
    
    // Calculate Levenshtein distance
    
    // Step 1
    int k, i, j, cost, * d, distance;
    
    NSUInteger n = [dataA length];
    NSUInteger m = [dataB length];
    
    if( n++ != 0 && m++ != 0 ) {
        
        d = malloc( sizeof(int) * m * n );
        
        // Step 2
        for( k = 0; k < n; k++)
            d[k] = k;
        
        for( k = 0; k < m; k++)
            d[ k * n ] = k;
        
        // Step 3 and 4
        for( i = 1; i < n; i++ )
            for( j = 1; j < m; j++ ) {
                
                // Step 5
                if( cstringA[i-1] == cstringB[j-1] )
                    cost = 0;
                else
                    cost = 1;
                
                // Step 6
                d[ j * n + i ] = smallestOf( d[ (j - 1) * n + i ] + 1,
                                            d[ j * n + i - 1 ] +  1,
                                            d[ (j - 1) * n + i -1 ] + cost );
            }
        
        distance = d[ n * m - 1 ];
        
        free( d );
        
        return distance;
    }
    return 0.0;
}

// return the minimum of a, b and c
int smallestOf(int a, int b, int c)
{
    int min = a;
    if ( b < min )
        min = b;
    
    if( c < min )
        min = c;
    
    return min;
}


@end


================================================
FILE: RCTAutoComplete.android.js
================================================
/**
 * Stub of RCTAutoComplete for Android.
 *
 * @providesModule RCTAutoComplete
 * @flow
 */
'use strict';

var warning = require('warning');

var RCTAutoComplete = {
  test: function() {
    warning("Not yet implemented for Android.");
  }
};

module.exports = RCTAutoComplete;


================================================
FILE: RCTAutoComplete.h
================================================
#import <React/RCTBridgeModule.h>
#import <React/RCTViewManager.h>
#import "MLPAutoCompleteTextField/MLPAutoCompleteTextField.h"

@interface RCTAutoComplete : RCTViewManager <MLPAutoCompleteTextFieldDataSource, MLPAutoCompleteTextFieldDelegate>

@end

================================================
FILE: RCTAutoComplete.ios.js
================================================
var React = require("react");
var PropTypes = require("prop-types");
var { requireNativeComponent } = require("react-native");

var NativeAutoComplete = requireNativeComponent("RCTAutoComplete", null);

class RCTAutoComplete extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      mostRecentEventCount: 0
    };
    this._getText = this._getText.bind(this);
    this._onChange = this._onChange.bind(this);
    this._onFocus = this._onFocus.bind(this);
    this._onBlur = this._onBlur.bind(this);
  }
  _getText() {
    return typeof this.props.value === "string"
      ? this.props.value
      : this.props.defaultValue;
  }
  _onChange(event) {
    var text = event.nativeEvent.text;
    var eventCount = event.nativeEvent.eventCount;
    this.props.onChange && this.props.onChange(event);
    this.props.onChangeText && this.props.onChangeText(text);
    this.setState({ mostRecentEventCount: eventCount }, () => {
      // This is a controlled component, so make sure to force the native value
      // to match.  Most usage shouldn't need this, but if it does this will be
      // more correct but might flicker a bit and/or cause the cursor to jump.
      if (text !== this.props.value && typeof this.props.value === "string") {
        this.refs.input &&
          this.refs.input.setNativeProps({
            text: this.props.value
          });
      }
    });

    event.nativeEvent.possibleCompletionsForString &&
      this.props.onTyping &&
      this.props.onTyping(event.nativeEvent.possibleCompletionsForString);

    event.nativeEvent.didSelectAutoCompleteString &&
      this.props.onSelect &&
      this.props.onSelect(event.nativeEvent.didSelectAutoCompleteString);
  }

  _onFocus(event) {
    if (this.props.onFocus) {
      this.props.onFocus(event);
    }
  }

  _onBlur(event) {
    if (this.props.onBlur) {
      this.props.onBlur(event);
    }
  }

  render() {
    var props = Object.assign({}, this.props);

    return (
      <NativeAutoComplete
        ref="autocomplete"
        {...props}
        onChange={this._onChange}
        onFocus={this._onFocus}
        onBlur={this._onBlur}
        onSelectionChangeShouldSetResponder={() => true}
        text={this._getText()}
        mostRecentEventCount={this.state.mostRecentEventCount}
      />
    );
  }
}

RCTAutoComplete.PropTypes = {
  /**
   * If false, disables auto-correct. The default value is true.
   */
  autoCorrect: PropTypes.bool,
  /**
   * The string that will be rendered before text input has been entered
   */
  placeholder: PropTypes.string,
  /**
   * When the clear button should appear on the right side of the text view
   * @platform ios
   */
  clearButtonMode: PropTypes.oneOf([
    "never",
    "while-editing",
    "unless-editing",
    "always"
  ]),
  /**
   * If true, clears the text field automatically when editing begins
   * @platform ios
   */
  clearTextOnFocus: PropTypes.bool,
  /**
   * Determines which keyboard to open, e.g.`numeric`.
   *
   * The following values work across platforms:
   * - default
   * - numeric
   * - email-address
   */
  keyboardType: PropTypes.oneOf([
    // Cross-platform
    "default",
    "numeric",
    "email-address",
    // iOS-only
    "ascii-capable",
    "numbers-and-punctuation",
    "url",
    "number-pad",
    "phone-pad",
    "name-phone-pad",
    "decimal-pad",
    "twitter",
    "web-search"
  ]),
  /**
   * Determines how the return key should look.
   * @platform ios
   */
  returnKeyType: PropTypes.oneOf([
    "default",
    "go",
    "google",
    "join",
    "next",
    "route",
    "search",
    "send",
    "yahoo",
    "done",
    "emergency-call"
  ]),
  /**
   * If true, the keyboard disables the return key when there is no text and
   * automatically enables it when there is text. The default value is false.
   * @platform ios
   */
  enablesReturnKeyAutomatically: PropTypes.bool,
  /**
   * Can tell TextInput to automatically capitalize certain characters.
   *
   * - characters: all characters,
   * - words: first letter of each word
   * - sentences: first letter of each sentence (default)
   * - none: don't auto capitalize anything
   */
  autoCapitalize: PropTypes.oneOf(["none", "sentences", "words", "characters"]),
  /**
   * Set the position of the cursor from where editing will begin.
   * @platorm android
   */
  textAlign: PropTypes.oneOf(["start", "center", "end"]),

  cellComponent: PropTypes.string,
  suggestions: PropTypes.array,
  autoCompleteFetchRequestDelay: PropTypes.number,
  maximumNumberOfAutoCompleteRows: PropTypes.number,
  showTextFieldDropShadowWhenAutoCompleteTableIsOpen: PropTypes.bool,
  autoCompleteTableViewHidden: PropTypes.bool,
  autoCompleteTableBorderColor: PropTypes.string,
  autoCompleteTableBorderWidth: PropTypes.number,
  autoCompleteTableBackgroundColor: PropTypes.string,
  autoCompleteTableCornerRadius: PropTypes.number,
  autoCompleteTableTopOffset: PropTypes.number,
  autoCompleteTableLeftOffset: PropTypes.number,
  autoCompleteTableSizeOffset: PropTypes.number,
  autoCompleteRowHeight: PropTypes.number,
  autoCompleteFontSize: PropTypes.number,
  autoCompleteRegularFontName: PropTypes.string,
  autoCompleteBoldFontName: PropTypes.string,
  autoCompleteTableCellTextColor: PropTypes.string,
  autoCompleteTableCellBackgroundColor: PropTypes.string,
  applyBoldEffectToAutoCompleteSuggestions: PropTypes.bool,
  reverseAutoCompleteSuggestionsBoldEffect: PropTypes.bool,
  disableAutoCompleteTableUserInteractionWhileFetching: PropTypes.bool
};

RCTAutoComplete.defaultProps = {
  autoCorrect: false,
  clearTextOnFocus: true,
  showTextFieldDropShadowWhenAutoCompleteTableIsOpen: true,
  reverseAutoCompleteSuggestionsBoldEffect: false,
  autoCompleteTableViewHidden: false,
  applyBoldEffectToAutoCompleteSuggestions: false,
  enablesReturnKeyAutomatically: false,
  disableAutoCompleteTableUserInteractionWhileFetching: false,
  placeholder: "Search a name",
  clearButtonMode: "while-editing",
  returnKeyType: "go",
  textAlign: "center",
  autoCompleteTableTopOffset: 10,
  autoCompleteTableLeftOffset: 20,
  autoCompleteTableSizeOffset: 40,
  autoCompleteTableBorderColor: "lightblue",
  autoCompleteTableBackgroundColor: "azure",
  autoCompleteTableCornerRadius: 8,
  autoCompleteTableBorderWidth: 1,
  autoCompleteFontSize: 18,
  autoCompleteRegularFontName: "Helvetica Neue",
  autoCompleteBoldFontName: "Helvetica Bold",
  autoCompleteTableCellTextColor: "dimgray",
  autoCompleteRowHeight: 40,
  autoCompleteFetchRequestDelay: 100,
  maximumNumberOfAutoCompleteRows: 6
};

module.exports = RCTAutoComplete;


================================================
FILE: RCTAutoComplete.m
================================================
#import <Foundation/Foundation.h>
#import "RCTAutoComplete.h"
#import "RCTTableViewCell.h"
#import <React/RCTEventDispatcher.h>
#import "UIView+React.h"
#import "AutoCompleteView.h"
#import "DictionaryAutoCompleteObject.h"
#import <React/RCTFont.h>

@implementation RCTAutoComplete

RCT_EXPORT_MODULE()

// From AutoCompleteView.m
RCT_EXPORT_VIEW_PROPERTY(suggestions, NSArray)
RCT_EXPORT_VIEW_PROPERTY(maximumNumberOfAutoCompleteRows, NSInteger)
RCT_EXPORT_VIEW_PROPERTY(applyBoldEffectToAutoCompleteSuggestions, BOOL)
RCT_EXPORT_VIEW_PROPERTY(reverseAutoCompleteSuggestionsBoldEffect, BOOL)
RCT_EXPORT_VIEW_PROPERTY(showTextFieldDropShadowWhenAutoCompleteTableIsOpen, BOOL);
RCT_EXPORT_VIEW_PROPERTY(autoCompleteTableViewHidden, BOOL);

RCT_EXPORT_VIEW_PROPERTY(autoCompleteTableBorderColor, UIColor);
RCT_EXPORT_VIEW_PROPERTY(autoCompleteTableBorderWidth, CGFloat);
RCT_EXPORT_VIEW_PROPERTY(autoCompleteTableBackgroundColor, UIColor);
RCT_EXPORT_VIEW_PROPERTY(autoCompleteTableCellBackgroundColor, UIColor);
RCT_EXPORT_VIEW_PROPERTY(autoCompleteTableCellTextColor, UIColor);
RCT_EXPORT_VIEW_PROPERTY(autoCompleteTableCornerRadius, CGFloat);

RCT_EXPORT_VIEW_PROPERTY(autoCompleteRowHeight, CGFloat);
RCT_EXPORT_VIEW_PROPERTY(autoCompleteFontSize, CGFloat);
RCT_EXPORT_VIEW_PROPERTY(autoCompleteBoldFontName, NSString);
RCT_EXPORT_VIEW_PROPERTY(autoCompleteRegularFontName, NSString);

RCT_CUSTOM_VIEW_PROPERTY(autoCompleteTableTopOffset, NSInteger, AutoCompleteView)
{
    CGSize size = view.autoCompleteTableOriginOffset;
    size.height = [RCTConvert NSInteger:json];
    view.autoCompleteTableOriginOffset = size;
}

RCT_CUSTOM_VIEW_PROPERTY(autoCompleteTableLeftOffset, NSInteger, AutoCompleteView)
{
    CGSize size = view.autoCompleteTableOriginOffset;
    size.width = [RCTConvert NSInteger:json];
    view.autoCompleteTableOriginOffset = size;
}


RCT_CUSTOM_VIEW_PROPERTY(autoCompleteTableSizeOffset, NSInteger, AutoCompleteView)
{
    view.autoCompleteTableSizeOffset = CGSizeMake([RCTConvert NSInteger:json], 0);
}

RCT_CUSTOM_VIEW_PROPERTY(cellComponent, NSString*, AutoCompleteView) {
    // Register RCTTableViewCellBridge (hosts cell React Component)
    [view registerAutoCompleteCellClass:[RCTTableViewCell class]
                 forCellReuseIdentifier:@"RCTTableViewCell"];
    // Set cell React Component
    [view setCellComponent:[RCTConvert NSString:json]];
}

RCT_EXPORT_VIEW_PROPERTY(autoCompleteFetchRequestDelay, NSTimeInterval);

// From RCTTextFieldManager.m
RCT_EXPORT_VIEW_PROPERTY(autoCorrect, BOOL)
RCT_EXPORT_VIEW_PROPERTY(text, NSString)
RCT_EXPORT_VIEW_PROPERTY(placeholder, NSString)
RCT_EXPORT_VIEW_PROPERTY(placeholderTextColor, UIColor)
RCT_EXPORT_VIEW_PROPERTY(clearButtonMode, UITextFieldViewMode)
RCT_REMAP_VIEW_PROPERTY(clearTextOnFocus, clearsOnBeginEditing, BOOL)
RCT_EXPORT_VIEW_PROPERTY(blurOnSubmit, BOOL)
RCT_EXPORT_VIEW_PROPERTY(keyboardType, UIKeyboardType)
RCT_EXPORT_VIEW_PROPERTY(returnKeyType, UIReturnKeyType)
RCT_EXPORT_VIEW_PROPERTY(enablesReturnKeyAutomatically, BOOL)
RCT_REMAP_VIEW_PROPERTY(color, textColor, UIColor)
RCT_REMAP_VIEW_PROPERTY(autoCapitalize, autocapitalizationType, UITextAutocapitalizationType)
RCT_REMAP_VIEW_PROPERTY(textAlign, textAlignment, NSTextAlignment)
RCT_CUSTOM_VIEW_PROPERTY(fontSize, NSNumber, AutoCompleteView)
{
    view.font = [RCTFont updateFont:view.font withSize:json ?: @(defaultView.font.pointSize)];
}
RCT_CUSTOM_VIEW_PROPERTY(fontWeight, NSString, __unused AutoCompleteView)
{
    view.font = [RCTFont updateFont:view.font withWeight:json]; // defaults to normal
}
RCT_CUSTOM_VIEW_PROPERTY(fontStyle, NSString, __unused AutoCompleteView)
{
    view.font = [RCTFont updateFont:view.font withStyle:json]; // defaults to normal
}
RCT_CUSTOM_VIEW_PROPERTY(fontFamily, NSString, AutoCompleteView)
{
    view.font = [RCTFont updateFont:view.font withFamily:json ?: defaultView.font.familyName];
}
RCT_EXPORT_VIEW_PROPERTY(mostRecentEventCount, NSInteger)

- (UIView *) view
{
    AutoCompleteView *searchTextField = [[AutoCompleteView alloc] initWithEventDispatcher:self.bridge.eventDispatcher];

    searchTextField.autoCompleteDataSource = self;
    searchTextField.autoCompleteDelegate = self;    
    searchTextField.showTextFieldDropShadowWhenAutoCompleteTableIsOpen = false;
    
    return searchTextField;
}

- (void)autoCompleteTextField:(AutoCompleteView *)textField
 possibleCompletionsForString:(NSString *)string
            completionHandler:(void (^)(NSArray *))handler
{
    // If empty string, empty the completion list
    if([string isEqualToString:@""]) {
        handler([NSArray array]);
    } else {
        textField.handler = handler;
        
        NSDictionary *event  = @{
            @"possibleCompletionsForString": string,
            @"target": textField.reactTag
        };
        
        [self.bridge.eventDispatcher sendInputEventWithName:@"topChange" body:event];
    }
}

- (BOOL)autoCompleteTextField:(MLPAutoCompleteTextField *)textField
          shouldConfigureCell:(UITableViewCell *)cell
       withAutoCompleteString:(NSString *)autocompleteString
         withAttributedString:(NSAttributedString *)boldedString
        forAutoCompleteObject:(id<MLPAutoCompletionObject>)autocompleteObject
            forRowAtIndexPath:(NSIndexPath *)indexPath;
{
    // If no registered Cell Component
    if (((AutoCompleteView*)textField).cellComponent == nil) {
        return YES;
    }
    
    RCTTableViewCell *customCell = (RCTTableViewCell*) cell;
    
    RCTBridge *_bridge = self.bridge;

    // 🚀 https://github.com/aksonov/react-native-tableview/blob/8982116711cd74e819a73237c53307839fe071ce/RNTableView/RNTableView.m#L87
    while ([_bridge respondsToSelector:NSSelectorFromString(@"parentBridge")]
           && [_bridge valueForKey:@"parentBridge"]) {
        _bridge = [_bridge valueForKey:@"parentBridge"];
    }
    
    [customCell initWithBridge:_bridge
                reactComponent:[(AutoCompleteView*)textField cellComponent]
                          json:[(DictionaryAutoCompleteObject*)autocompleteObject json]
    ];
    
    return YES;
}

- (void)autoCompleteTextField:(MLPAutoCompleteTextField *)textField
  didSelectAutoCompleteString:(NSString *)selectedString
       withAutoCompleteObject:(id<MLPAutoCompletionObject>)selectedObject
            forRowAtIndexPath:(NSIndexPath *)indexPath
{
    
    NSDictionary *event = selectedObject
        ? @{
          @"target": textField.reactTag,
          @"didSelectAutoCompleteString": [(DictionaryAutoCompleteObject*)selectedObject json]
        }
        : @{
          @"target": textField.reactTag,
          @"didSelectAutoCompleteString": selectedString
        };
    
    [self.bridge.eventDispatcher sendInputEventWithName:@"topChange" body:event];
}

@end


================================================
FILE: RCTAutoComplete.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
	archiveVersion = 1;
	classes = {
	};
	objectVersion = 46;
	objects = {

/* Begin PBXBuildFile section */
		13BE3DEE1AC21097009241FE /* RCTAutoComplete.m in Sources */ = {isa = PBXBuildFile; fileRef = 13BE3DED1AC21097009241FE /* RCTAutoComplete.m */; };
		37005CB01E5720DB00FE0899 /* DictionaryAutoCompleteObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 37005CAF1E5720DB00FE0899 /* DictionaryAutoCompleteObject.m */; };
		3798A8D81D9B09D500348235 /* AutoCompleteView.m in Sources */ = {isa = PBXBuildFile; fileRef = 3798A8D61D9B09D500348235 /* AutoCompleteView.m */; };
		3798A8F51D9B0B0900348235 /* MLPAutoCompleteTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = 3798A8EF1D9B0B0900348235 /* MLPAutoCompleteTextField.m */; };
		3798A8F61D9B0B0900348235 /* NSString+Levenshtein.m in Sources */ = {isa = PBXBuildFile; fileRef = 3798A8F41D9B0B0900348235 /* NSString+Levenshtein.m */; };
		37DBC8B31E4496DE00317A45 /* RCTTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 37DBC8B21E4496DE00317A45 /* RCTTableViewCell.m */; };
/* End PBXBuildFile section */

/* Begin PBXCopyFilesBuildPhase section */
		58B511D91A9E6C8500147676 /* CopyFiles */ = {
			isa = PBXCopyFilesBuildPhase;
			buildActionMask = 2147483647;
			dstPath = "include/$(PRODUCT_NAME)";
			dstSubfolderSpec = 16;
			files = (
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
		134814201AA4EA6300B7C361 /* libRCTAutoComplete.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRCTAutoComplete.a; sourceTree = BUILT_PRODUCTS_DIR; };
		13BE3DEC1AC21097009241FE /* RCTAutoComplete.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTAutoComplete.h; sourceTree = "<group>"; };
		13BE3DED1AC21097009241FE /* RCTAutoComplete.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTAutoComplete.m; sourceTree = "<group>"; };
		37005CAE1E5720B500FE0899 /* DictionaryAutoCompleteObject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DictionaryAutoCompleteObject.h; sourceTree = "<group>"; };
		37005CAF1E5720DB00FE0899 /* DictionaryAutoCompleteObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DictionaryAutoCompleteObject.m; sourceTree = "<group>"; };
		3798A8D51D9B09D500348235 /* AutoCompleteView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AutoCompleteView.h; sourceTree = "<group>"; };
		3798A8D61D9B09D500348235 /* AutoCompleteView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AutoCompleteView.m; sourceTree = "<group>"; };
		3798A8EE1D9B0B0900348235 /* MLPAutoCompleteTextField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MLPAutoCompleteTextField.h; path = MLPAutoCompleteTextField/MLPAutoCompleteTextField.h; sourceTree = "<group>"; };
		3798A8EF1D9B0B0900348235 /* MLPAutoCompleteTextField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MLPAutoCompleteTextField.m; path = MLPAutoCompleteTextField/MLPAutoCompleteTextField.m; sourceTree = "<group>"; };
		3798A8F01D9B0B0900348235 /* MLPAutoCompleteTextFieldDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MLPAutoCompleteTextFieldDataSource.h; path = MLPAutoCompleteTextField/MLPAutoCompleteTextFieldDataSource.h; sourceTree = "<group>"; };
		3798A8F11D9B0B0900348235 /* MLPAutoCompleteTextFieldDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MLPAutoCompleteTextFieldDelegate.h; path = MLPAutoCompleteTextField/MLPAutoCompleteTextFieldDelegate.h; sourceTree = "<group>"; };
		3798A8F21D9B0B0900348235 /* MLPAutoCompletionObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MLPAutoCompletionObject.h; path = MLPAutoCompleteTextField/MLPAutoCompletionObject.h; sourceTree = "<group>"; };
		3798A8F31D9B0B0900348235 /* NSString+Levenshtein.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSString+Levenshtein.h"; path = "MLPAutoCompleteTextField/NSString+Levenshtein.h"; sourceTree = "<group>"; };
		3798A8F41D9B0B0900348235 /* NSString+Levenshtein.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSString+Levenshtein.m"; path = "MLPAutoCompleteTextField/NSString+Levenshtein.m"; sourceTree = "<group>"; };
		37DBC8B11E44965900317A45 /* RCTTableViewCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RCTTableViewCell.h; sourceTree = "<group>"; };
		37DBC8B21E4496DE00317A45 /* RCTTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTTableViewCell.m; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
		58B511D81A9E6C8500147676 /* Frameworks */ = {
			isa = PBXFrameworksBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
		134814211AA4EA7D00B7C361 /* Products */ = {
			isa = PBXGroup;
			children = (
				134814201AA4EA6300B7C361 /* libRCTAutoComplete.a */,
			);
			name = Products;
			sourceTree = "<group>";
		};
		3798A8E41D9B0ACB00348235 /* MLPAutoCompleteTextField */ = {
			isa = PBXGroup;
			children = (
				3798A8EE1D9B0B0900348235 /* MLPAutoCompleteTextField.h */,
				3798A8EF1D9B0B0900348235 /* MLPAutoCompleteTextField.m */,
				3798A8F01D9B0B0900348235 /* MLPAutoCompleteTextFieldDataSource.h */,
				3798A8F11D9B0B0900348235 /* MLPAutoCompleteTextFieldDelegate.h */,
				3798A8F21D9B0B0900348235 /* MLPAutoCompletionObject.h */,
				3798A8F31D9B0B0900348235 /* NSString+Levenshtein.h */,
				3798A8F41D9B0B0900348235 /* NSString+Levenshtein.m */,
			);
			name = MLPAutoCompleteTextField;
			sourceTree = "<group>";
		};
		58B511D21A9E6C8500147676 = {
			isa = PBXGroup;
			children = (
				37005CAF1E5720DB00FE0899 /* DictionaryAutoCompleteObject.m */,
				37005CAE1E5720B500FE0899 /* DictionaryAutoCompleteObject.h */,
				37DBC8B21E4496DE00317A45 /* RCTTableViewCell.m */,
				37DBC8B11E44965900317A45 /* RCTTableViewCell.h */,
				3798A8E41D9B0ACB00348235 /* MLPAutoCompleteTextField */,
				3798A8D51D9B09D500348235 /* AutoCompleteView.h */,
				3798A8D61D9B09D500348235 /* AutoCompleteView.m */,
				13BE3DEC1AC21097009241FE /* RCTAutoComplete.h */,
				13BE3DED1AC21097009241FE /* RCTAutoComplete.m */,
				134814211AA4EA7D00B7C361 /* Products */,
			);
			sourceTree = "<group>";
		};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
		58B511DA1A9E6C8500147676 /* RCTAutoComplete */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RCTAutoComplete" */;
			buildPhases = (
				58B511D71A9E6C8500147676 /* Sources */,
				58B511D81A9E6C8500147676 /* Frameworks */,
				58B511D91A9E6C8500147676 /* CopyFiles */,
			);
			buildRules = (
			);
			dependencies = (
			);
			name = RCTAutoComplete;
			productName = RCTDataManager;
			productReference = 134814201AA4EA6300B7C361 /* libRCTAutoComplete.a */;
			productType = "com.apple.product-type.library.static";
		};
/* End PBXNativeTarget section */

/* Begin PBXProject section */
		58B511D31A9E6C8500147676 /* Project object */ = {
			isa = PBXProject;
			attributes = {
				LastUpgradeCheck = 0610;
				ORGANIZATIONNAME = Facebook;
				TargetAttributes = {
					58B511DA1A9E6C8500147676 = {
						CreatedOnToolsVersion = 6.1.1;
					};
				};
			};
			buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RCTAutoComplete" */;
			compatibilityVersion = "Xcode 3.2";
			developmentRegion = English;
			hasScannedForEncodings = 0;
			knownRegions = (
				en,
			);
			mainGroup = 58B511D21A9E6C8500147676;
			productRefGroup = 58B511D21A9E6C8500147676;
			projectDirPath = "";
			projectRoot = "";
			targets = (
				58B511DA1A9E6C8500147676 /* RCTAutoComplete */,
			);
		};
/* End PBXProject section */

/* Begin PBXSourcesBuildPhase section */
		58B511D71A9E6C8500147676 /* Sources */ = {
			isa = PBXSourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				3798A8F51D9B0B0900348235 /* MLPAutoCompleteTextField.m in Sources */,
				37005CB01E5720DB00FE0899 /* DictionaryAutoCompleteObject.m in Sources */,
				37DBC8B31E4496DE00317A45 /* RCTTableViewCell.m in Sources */,
				3798A8F61D9B0B0900348235 /* NSString+Levenshtein.m in Sources */,
				3798A8D81D9B09D500348235 /* AutoCompleteView.m in Sources */,
				13BE3DEE1AC21097009241FE /* RCTAutoComplete.m in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXSourcesBuildPhase section */

/* Begin XCBuildConfiguration section */
		58B511ED1A9E6C8500147676 /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_MODULES = YES;
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				COPY_PHASE_STRIP = NO;
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				GCC_C_LANGUAGE_STANDARD = gnu99;
				GCC_DYNAMIC_NO_PIC = NO;
				GCC_OPTIMIZATION_LEVEL = 0;
				GCC_PREPROCESSOR_DEFINITIONS = (
					"DEBUG=1",
					"$(inherited)",
				);
				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
				MTL_ENABLE_DEBUG_INFO = YES;
				ONLY_ACTIVE_ARCH = YES;
				SDKROOT = iphoneos;
			};
			name = Debug;
		};
		58B511EE1A9E6C8500147676 /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_MODULES = YES;
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				COPY_PHASE_STRIP = YES;
				ENABLE_NS_ASSERTIONS = NO;
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				GCC_C_LANGUAGE_STANDARD = gnu99;
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
				MTL_ENABLE_DEBUG_INFO = NO;
				SDKROOT = iphoneos;
				VALIDATE_PRODUCT = YES;
			};
			name = Release;
		};
		58B511F01A9E6C8500147676 /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				HEADER_SEARCH_PATHS = (
					"$(inherited)",
					/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
					"$(SRCROOT)/../../React/**",
					"$(SRCROOT)/../../node_modules/react-native/React/**",
				);
				LIBRARY_SEARCH_PATHS = "$(inherited)";
				OTHER_LDFLAGS = "-ObjC";
				PRODUCT_NAME = RCTAutoComplete;
				SKIP_INSTALL = YES;
			};
			name = Debug;
		};
		58B511F11A9E6C8500147676 /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				HEADER_SEARCH_PATHS = (
					"$(inherited)",
					/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
					"$(SRCROOT)/../../React/**",
					"$(SRCROOT)/../../node_modules/react-native/React/**",
				);
				LIBRARY_SEARCH_PATHS = "$(inherited)";
				OTHER_LDFLAGS = "-ObjC";
				PRODUCT_NAME = RCTAutoComplete;
				SKIP_INSTALL = YES;
			};
			name = Release;
		};
/* End XCBuildConfiguration section */

/* Begin XCConfigurationList section */
		58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RCTAutoComplete" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				58B511ED1A9E6C8500147676 /* Debug */,
				58B511EE1A9E6C8500147676 /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
		58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RCTAutoComplete" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				58B511F01A9E6C8500147676 /* Debug */,
				58B511F11A9E6C8500147676 /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
/* End XCConfigurationList section */
	};
	rootObject = 58B511D31A9E6C8500147676 /* Project object */;
}


================================================
FILE: RCTTableViewCell.h
================================================
#import <React/RCTRootView.h>
#import <UIKit/UIKit.h>

@interface RCTTableViewCell : UITableViewCell
@property (strong, nonatomic) RCTRootView *view;
-(void)initWithBridge:(RCTBridge*)bridge reactComponent:(NSString*)reactComponent json:(NSDictionary*)json;
@end


================================================
FILE: RCTTableViewCell.m
================================================
#import <React/RCTRootView.h>
#import "RCTTableViewCell.h"

@implementation RCTTableViewCell

@synthesize view;

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    return [super initWithStyle:style reuseIdentifier:reuseIdentifier];
}

-(void)initWithBridge:(RCTBridge*)bridge reactComponent:(NSString*)reactComponent json:(NSDictionary*)json  {
    if (view == nil) {
        view = [[RCTRootView alloc] initWithBridge:bridge moduleName:reactComponent initialProperties:@{@"data": json}];
        [self.contentView addSubview:view];
        view.frame = self.contentView.frame;
    } else {
        view.appProperties = @{@"data": json};
    }
}

@end


================================================
FILE: README.md
================================================
# react-native-autocomplete

[MLPAutoCompleteTextField](https://github.com/EddyBorja/MLPAutoCompleteTextField)
(iOS only) wrapper for React Native, supports React Native custom cells 🎨.

![Demo gif](https://raw.githubusercontent.com/nulrich/RCTAutoComplete/master/demo.gif)

## Installation

* `$ npm install react-native-autocomplete`
* Right click on Libraries, select **Add files to "…"** and select
  `node_modules/react-native-autocomplete/RCTAutoComplete.xcodeproj`
* Select your project and under **Build Phases** -> **Link Binary With
  Libraries**, press the + and select `libRCTAutoComplete.a`.

[Facebook documentation](https://facebook.github.io/react-native/docs/linking-libraries.html#content)

## Usage

For example download
[Country list](https://gist.githubusercontent.com/Keeguon/2310008/raw/865a58f59b9db2157413e7d3d949914dbf5a237d/countries.json)

```js
import React, { Component } from "react";
import { AppRegistry, StyleSheet, Text, View, AlertIOS } from "react-native";

import AutoComplete from "react-native-autocomplete";
import Countries from "./countries.json";

const styles = StyleSheet.create({
  autocomplete: {
    alignSelf: "stretch",
    height: 50,
    margin: 10,
    marginTop: 50,
    backgroundColor: "#FFF",
    borderColor: "lightblue",
    borderWidth: 1
  },
  container: {
    flex: 1,
    backgroundColor: "#F5FCFF"
  }
});

class RCTAutoCompleteApp extends Component {
  state = { data: [] };

  constructor(props) {
    super(props);
    this.onTyping = this.onTyping.bind(this);
  }

  onTyping(text) {
    const countries = Countries.filter(country =>
      country.name.toLowerCase().startsWith(text.toLowerCase())
    ).map(country => country.name);

    this.setState({ data: countries });
  }

  onSelect(value) {
    AlertIOS.alert("You choosed", value);
  }

  render() {
    return (
      <View style={styles.container}>
        <AutoComplete
          style={styles.autocomplete}
          suggestions={this.state.data}
          onTyping={this.onTyping}
          onSelect={this.onSelect}
          placeholder="Search for a country"
          clearButtonMode="always"
          returnKeyType="go"
          textAlign="center"
          clearTextOnFocus
          autoCompleteTableTopOffset={10}
          autoCompleteTableLeftOffset={20}
          autoCompleteTableSizeOffset={-40}
          autoCompleteTableBorderColor="lightblue"
          autoCompleteTableBackgroundColor="azure"
          autoCompleteTableCornerRadius={8}
          autoCompleteTableBorderWidth={1}
          autoCompleteFontSize={15}
          autoCompleteRegularFontName="Helvetica Neue"
          autoCompleteBoldFontName="Helvetica Bold"
          autoCompleteTableCellTextColor={"dimgray"}
          autoCompleteRowHeight={40}
          autoCompleteFetchRequestDelay={100}
          maximumNumberOfAutoCompleteRows={6}
        />
      </View>
    );
  }
}

AppRegistry.registerComponent("RCTAutoCompleteApp", () => RCTAutoCompleteApp);
```

# Custom Cell

You can use a React Native component to render the cells.

```js
import React, { Component } from "react";
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  Image,
  AlertIOS
} from "react-native";

import AutoComplete from "react-native-autocomplete";
import Countries from "./countries.json";

const flag = code =>
  `https://raw.githubusercontent.com/hjnilsson/country-flags/master/png250px/${
    code
  }.png`;

const styles = StyleSheet.create({
  autocomplete: {
    alignSelf: "stretch",
    height: 50,
    margin: 10,
    marginTop: 50,
    backgroundColor: "#FFF",
    borderColor: "lightblue",
    borderWidth: 1
  },
  cell: {
    flex: 1,
    borderWidth: 1,
    borderColor: "lightblue",
    flexDirection: "row",
    justifyContent: "center",
    alignItems: "center"
  },
  cellText: {
    flex: 1,
    marginLeft: 10
  },
  image: {
    width: 20,
    height: 20,
    marginLeft: 10
  },
  container: {
    flex: 1,
    backgroundColor: "#F5FCFF"
  }
});

const CustomCell = ({ data }) => (
  <View style={styles.cell}>
    <Image source={{ uri: flag(data.code) }} style={styles.image} />
    <Text style={styles.cellText}>{data.country}</Text>
  </View>
);

class RCTAutoCompleteApp extends Component {
  state = { data: [] };

  constructor(props) {
    super(props);
    this.onTyping = this.onTyping.bind(this);
  }

  onTyping(text) {
    const countries = Countries.filter(country =>
      country.name.toLowerCase().startsWith(text.toLowerCase())
    ).map(country => {
      return { country: country.name, code: country.code.toLowerCase() };
    });

    this.setState({ data: countries });
  }

  onSelect(json) {
    AlertIOS.alert("You choosed", json.country);
  }

  render() {
    return (
      <View style={styles.container}>
        <AutoComplete
          style={styles.autocomplete}
          cellComponent="CustomCell"
          suggestions={this.state.data}
          onTyping={this.onTyping}
          onSelect={this.onSelect}
          placeholder="Search for a country"
          clearButtonMode="always"
          returnKeyType="go"
          textAlign="center"
          clearTextOnFocus
          autoCompleteTableTopOffset={10}
          autoCompleteTableLeftOffset={20}
          autoCompleteTableSizeOffset={-40}
          autoCompleteTableBorderColor="lightblue"
          autoCompleteTableBackgroundColor="azure"
          autoCompleteTableCornerRadius={8}
          autoCompleteTableBorderWidth={1}
          autoCompleteRowHeight={40}
          autoCompleteFetchRequestDelay={100}
          maximumNumberOfAutoCompleteRows={6}
        />
      </View>
    );
  }
}

AppRegistry.registerComponent("CustomCell", () => CustomCell);
AppRegistry.registerComponent("RCTAutoCompleteApp", () => RCTAutoCompleteApp);
```

## Events

| event    | Info                                                                                      |
| -------- | ----------------------------------------------------------------------------------------- |
| onTyping | Text is entered. The callback can be delayed with option `autoCompleteFetchRequestDelay`. |
| onSelect | A cell in the suggestions list is selected.                                               |
| onFocus  | Text input get focus.                                                                     |
| onBlur   | Text input lost focus.                                                                    |

> > Other events from Text Input are avalaible.

## Global options

| option                                             | type   | Info                                                                                                                                                                                                                              |
| -------------------------------------------------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| cellComponent                                      | string | Name of a React Native component used to render cells. If `null`, use the default rendering.                                                                                                                                      |
| suggestions                                        | array  | If using default cell rendering specify an Array of string, otherwise any object.                                                                                                                                                 |
| autoCompleteFetchRequestDelay                      | number | Delay in milliseconds before retrieving suggestions.                                                                                                                                                                              |
| maximumNumberOfAutoCompleteRows                    | number | Number of suggestions displayed.                                                                                                                                                                                                  |
| showTextFieldDropShadowWhenAutoCompleteTableIsOpen | bool   | Display a drop shadow around the text field.                                                                                                                                                                                      |
| autoCompleteTableViewHidden                        | bool   | If true, the suggestions list will be hidden.                                                                                                                                                                                     |
| autoCompleteTableBorderColor                       | color  | Set suggestions list border color.                                                                                                                                                                                                |
| autoCompleteTableBorderWidth                       | number | Set suggestions list border color.                                                                                                                                                                                                |
| autoCompleteTableBackgroundColor                   | color  | Set suggestions list border size.                                                                                                                                                                                                 |
| autoCompleteTableCornerRadius                      | number | Set suggestions list background color.                                                                                                                                                                                            |
| autoCompleteTableTopOffset                         | number | Set the distance between the text field and the suggestions list.                                                                                                                                                                 |
| autoCompleteTableLeftOffset                        | number | Set the left offset between the container and the suggestions list.                                                                                                                                                               |
| autoCompleteTableSizeOffset                        | number | Set the offset of the suggestions list size. Combined with autoCompleteTableLeftOffset, you can reduce the width of the suggestions list and to center it. Exemple: autoCompleteTableLeftOffset=20 autoCompleteTableSizeOffset=40 |
| autoCompleteRowHeight                              | number | Height of cells in the suggestions list.                                                                                                                                                                                          |

## Default cell rendering options

| option                                   | type   | Info                                              |
| ---------------------------------------- | ------ | ------------------------------------------------- |
| autoCompleteFontSize                     | number | Font Size used to display text.                   |
| autoCompleteRegularFontName              | string | Font used to display text.                        |
| autoCompleteBoldFontName                 | string | Font used to display suggestion text.             |
| autoCompleteTableCellTextColor           | color  | Text Color used to display text.                  |
| autoCompleteTableCellBackgroundColor     | color  | Background color of cells.                        |
| applyBoldEffectToAutoCompleteSuggestions | bool   | If false, disable bold effect on suggestion text. |
| reverseAutoCompleteSuggestionsBoldEffect | bool   | Reverse the bold effect.                          |

## License

MIT © Nicolas Ulrich 2017


================================================
FILE: package.json
================================================
{
  "name": "react-native-autocomplete",
  "author": "Nicolas Ulrich <github@ulrich.co> (https://github.com/nulrich)",
  "description": "React Native Component for MLPAutoCompleteTextField",
  "version": "0.4.0",
  "main": "RCTAutoComplete.ios.js",
  "repository": {
    "type": "git",
    "url": "https://github.com/nulrich/RCTAutoComplete.git"
  },
  "license": "MIT",
  "keywords": ["react-component", "react-native", "ios", "autocomplete"],
  "peerDependencies": {
    "react-native": ">=0.40.0"
  }
}


================================================
FILE: react-native-autocomplete.podspec
================================================
Pod::Spec.new do |s|
  s.name             = "react-native-autocomplete"
  s.version          = "0.4.0"
  s.summary          = "React Native Component for MLPAutoCompleteTextField"
  s.requires_arc = true
  s.author       = { 'Nicolas Ulrich' => 'github@ulrich.co' }
  s.license      = 'MIT'
  s.homepage     = 'https://github.com/nulrich/RCTAutoComplete'
  s.source       = { :git => "https://github.com/nulrich/RCTAutoComplete.git" }
  s.platform     = :ios, "7.0"
  s.dependency 'React'

  s.subspec 'MLPAutoCompleteTextField' do |ss|
    ss.source_files     = "MLPAutoCompleteTextField/*.{h,m}"
  end

  s.subspec 'RCTAutoComplete' do |ss|
    ss.dependency         'react-native-autocomplete/MLPAutoCompleteTextField'
    ss.source_files     = "*.{h,m}"
    ss.preserve_paths   = "*.js"
  end
end
Download .txt
gitextract_dsah9vym/

├── .flowconfig
├── .gitignore
├── .npmignore
├── AutoCompleteView.h
├── AutoCompleteView.m
├── DictionaryAutoCompleteObject.h
├── DictionaryAutoCompleteObject.m
├── LICENSE
├── MLPAutoCompleteTextField/
│   ├── MLPAutoCompleteTextField.h
│   ├── MLPAutoCompleteTextField.m
│   ├── MLPAutoCompleteTextFieldDataSource.h
│   ├── MLPAutoCompleteTextFieldDelegate.h
│   ├── MLPAutoCompletionObject.h
│   ├── NSString+Levenshtein.h
│   └── NSString+Levenshtein.m
├── RCTAutoComplete.android.js
├── RCTAutoComplete.h
├── RCTAutoComplete.ios.js
├── RCTAutoComplete.m
├── RCTAutoComplete.xcodeproj/
│   └── project.pbxproj
├── RCTTableViewCell.h
├── RCTTableViewCell.m
├── README.md
├── package.json
└── react-native-autocomplete.podspec
Download .txt
SYMBOL INDEX (7 symbols across 1 files)

FILE: RCTAutoComplete.ios.js
  class RCTAutoComplete (line 7) | class RCTAutoComplete extends React.Component {
    method constructor (line 8) | constructor(props) {
    method _getText (line 18) | _getText() {
    method _onChange (line 23) | _onChange(event) {
    method _onFocus (line 49) | _onFocus(event) {
    method _onBlur (line 55) | _onBlur(event) {
    method render (line 61) | render() {
Condensed preview — 25 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (121K chars).
[
  {
    "path": ".flowconfig",
    "chars": 943,
    "preview": "[ignore]\n\n# We fork some components by platform.\n.*/*.web.js\n.*/*.android.js\n\n# Some modules have their own node_modules"
  },
  {
    "path": ".gitignore",
    "chars": 294,
    "preview": "# OSX\n#\n.DS_Store\n\n# Xcode\n#\nbuild/\n*.pbxuser\n!default.pbxuser\n*.mode1v3\n!default.mode1v3\n*.mode2v3\n!default.mode2v3\n*.p"
  },
  {
    "path": ".npmignore",
    "chars": 274,
    "preview": "# OSX\n#\n.DS_Store\n\n# Xcode\n#\nbuild/\n*.pbxuser\n!default.pbxuser\n*.mode1v3\n!default.mode1v3\n*.mode2v3\n!default.mode2v3\n*.p"
  },
  {
    "path": "AutoCompleteView.h",
    "chars": 917,
    "preview": "#import <UIKit/UIKit.h>\n#import \"MLPAutoCompleteTextField/MLPAutoCompleteTextField.h\"\n\n@class RCTEventDispatcher;\n\n\n@int"
  },
  {
    "path": "AutoCompleteView.m",
    "chars": 7316,
    "preview": "#import \"AutoCompleteView.h\"\n#import \"DictionaryAutoCompleteObject.h\"\n\n#import \"MLPAutoCompleteTextField/MLPAutoComplete"
  },
  {
    "path": "DictionaryAutoCompleteObject.h",
    "chars": 249,
    "preview": "#import <Foundation/Foundation.h>\n#import \"MLPAutoCompletionObject.h\"\n\n@interface DictionaryAutoCompleteObject : NSObjec"
  },
  {
    "path": "DictionaryAutoCompleteObject.m",
    "chars": 391,
    "preview": "#import \"DictionaryAutoCompleteObject.h\"\n\n@interface DictionaryAutoCompleteObject ()\n@end\n\n@implementation DictionaryAut"
  },
  {
    "path": "LICENSE",
    "chars": 1058,
    "preview": "Copyright (c) 2015 Nicolas Ulrich\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this "
  },
  {
    "path": "MLPAutoCompleteTextField/MLPAutoCompleteTextField.h",
    "chars": 5187,
    "preview": "/*\n //  MLPAutoCompleteTextField.h\n //\n //\n //  Created by Eddy Borja on 12/29/12.\n //  Copyright (c) 2013 Mainloop LLC."
  },
  {
    "path": "MLPAutoCompleteTextField/MLPAutoCompleteTextField.m",
    "chars": 42632,
    "preview": "/*\n //  MLPAutoCompleteTextField.m\n //\n //\n //  Created by Eddy Borja on 12/29/12.\n //  Copyright (c) 2013 Mainloop LLC."
  },
  {
    "path": "MLPAutoCompleteTextField/MLPAutoCompleteTextFieldDataSource.h",
    "chars": 2278,
    "preview": "/*\n //  MLPAutoCompleteTextFieldDataSource.h\n //\n //\n //  Created by Eddy Borja on 12/29/12.\n //  Copyright (c) 2013 Mai"
  },
  {
    "path": "MLPAutoCompleteTextField/MLPAutoCompleteTextFieldDelegate.h",
    "chars": 3191,
    "preview": "/*\n //  MLPAutoCompleteTextFieldDelegate.h\n //\n //\n //  Created by Eddy Borja on 2/5/13.\n //  Copyright (c) 2013 Mainloo"
  },
  {
    "path": "MLPAutoCompleteTextField/MLPAutoCompletionObject.h",
    "chars": 1947,
    "preview": "/*\n //  MLPAutoCompletionObject.h\n //\n //\n //  Created by Eddy Borja on 4/19/13.\n //  Copyright (c) 2013 Mainloop LLC. A"
  },
  {
    "path": "MLPAutoCompleteTextField/NSString+Levenshtein.h",
    "chars": 2078,
    "preview": "//\n//  NSString+Levenshtein.h\n//\n//  Created by Mark Aufflick on 9/11/09.\n//  Copyright 2009 pumptheory.com. All rights "
  },
  {
    "path": "MLPAutoCompleteTextField/NSString+Levenshtein.m",
    "chars": 4516,
    "preview": "//\n//  NSString+Levenshtein.m\n//\n//  Created by Mark Aufflick on 9/11/09.\n//  mark@aufflick.com <http://mark.aufflick.co"
  },
  {
    "path": "RCTAutoComplete.android.js",
    "chars": 281,
    "preview": "/**\n * Stub of RCTAutoComplete for Android.\n *\n * @providesModule RCTAutoComplete\n * @flow\n */\n'use strict';\n\nvar warnin"
  },
  {
    "path": "RCTAutoComplete.h",
    "chars": 250,
    "preview": "#import <React/RCTBridgeModule.h>\n#import <React/RCTViewManager.h>\n#import \"MLPAutoCompleteTextField/MLPAutoCompleteText"
  },
  {
    "path": "RCTAutoComplete.ios.js",
    "chars": 6619,
    "preview": "var React = require(\"react\");\nvar PropTypes = require(\"prop-types\");\nvar { requireNativeComponent } = require(\"react-nat"
  },
  {
    "path": "RCTAutoComplete.m",
    "chars": 6782,
    "preview": "#import <Foundation/Foundation.h>\n#import \"RCTAutoComplete.h\"\n#import \"RCTTableViewCell.h\"\n#import <React/RCTEventDispat"
  },
  {
    "path": "RCTAutoComplete.xcodeproj/project.pbxproj",
    "chars": 13464,
    "preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
  },
  {
    "path": "RCTTableViewCell.h",
    "chars": 263,
    "preview": "#import <React/RCTRootView.h>\n#import <UIKit/UIKit.h>\n\n@interface RCTTableViewCell : UITableViewCell\n@property (strong, "
  },
  {
    "path": "RCTTableViewCell.m",
    "chars": 699,
    "preview": "#import <React/RCTRootView.h>\n#import \"RCTTableViewCell.h\"\n\n@implementation RCTTableViewCell\n\n@synthesize view;\n\n- (id)i"
  },
  {
    "path": "README.md",
    "chars": 12179,
    "preview": "# react-native-autocomplete\n\n[MLPAutoCompleteTextField](https://github.com/EddyBorja/MLPAutoCompleteTextField)\n(iOS only"
  },
  {
    "path": "package.json",
    "chars": 506,
    "preview": "{\n  \"name\": \"react-native-autocomplete\",\n  \"author\": \"Nicolas Ulrich <github@ulrich.co> (https://github.com/nulrich)\",\n "
  },
  {
    "path": "react-native-autocomplete.podspec",
    "chars": 801,
    "preview": "Pod::Spec.new do |s|\n  s.name             = \"react-native-autocomplete\"\n  s.version          = \"0.4.0\"\n  s.summary      "
  }
]

About this extraction

This page contains the full source code of the nulrich/RCTAutoComplete GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 25 files (112.4 KB), approximately 26.7k tokens, and a symbol index with 7 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!