diff --git a/.DS_Store b/.DS_Store index 7aee18b..7227ea6 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/AutocompleteTextfieldSwift.xcodeproj/project.pbxproj b/AutocompleteTextfieldSwift.xcodeproj/project.pbxproj index 53a9c2d..c35e365 100644 --- a/AutocompleteTextfieldSwift.xcodeproj/project.pbxproj +++ b/AutocompleteTextfieldSwift.xcodeproj/project.pbxproj @@ -7,6 +7,9 @@ objects = { /* Begin PBXBuildFile section */ + 700620251DBE0B4100065B51 /* UserModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 700620241DBE0B4100065B51 /* UserModel.swift */; }; + 700620271DBE0B5700065B51 /* AutoCompletionTextProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 700620261DBE0B5700065B51 /* AutoCompletionTextProtocol.swift */; }; + 700620281DBE0EE000065B51 /* AutoCompletionTextProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 700620261DBE0B5700065B51 /* AutoCompletionTextProtocol.swift */; }; F905D60F1B419684009DA356 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = F905D60B1B419684009DA356 /* LaunchScreen.xib */; }; F905D6101B419684009DA356 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F905D60D1B419684009DA356 /* Main.storyboard */; }; F96E31911A98DC36001DCEBF /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F96E31901A98DC36001DCEBF /* Images.xcassets */; }; @@ -31,6 +34,8 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 700620241DBE0B4100065B51 /* UserModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = UserModel.swift; path = ../UserModel.swift; sourceTree = ""; }; + 700620261DBE0B5700065B51 /* AutoCompletionTextProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AutoCompletionTextProtocol.swift; path = AutocompleteTextfieldSwift/AutoCompleteTextField/AutoCompletionTextProtocol.swift; sourceTree = SOURCE_ROOT; }; F905D60C1B419684009DA356 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = AutocompleteTextfieldSwift/Base.lproj/LaunchScreen.xib; sourceTree = SOURCE_ROOT; }; F905D60E1B419684009DA356 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = AutocompleteTextfieldSwift/Base.lproj/Main.storyboard; sourceTree = SOURCE_ROOT; }; F96E31841A98DC35001DCEBF /* AutocompleteTextfieldSwift.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AutocompleteTextfieldSwift.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -156,7 +161,9 @@ F9DD71CD1CA3F20200B17E74 /* AutocompleteTextField */ = { isa = PBXGroup; children = ( + 700620241DBE0B4100065B51 /* UserModel.swift */, F9DD71CE1CA3F20200B17E74 /* AutoCompleteTextField.swift */, + 700620261DBE0B5700065B51 /* AutoCompletionTextProtocol.swift */, ); path = AutocompleteTextField; sourceTree = ""; @@ -265,8 +272,10 @@ files = ( F99A8A3C1A99ADAF00DFD19D /* MKMapViewExtension.swift in Sources */, F9DD71CF1CA3F20200B17E74 /* AutoCompleteTextField.swift in Sources */, + 700620271DBE0B5700065B51 /* AutoCompletionTextProtocol.swift in Sources */, F96E31B51A98DCA3001DCEBF /* ViewController.swift in Sources */, F96E31B41A98DCA3001DCEBF /* AppDelegate.swift in Sources */, + 700620251DBE0B4100065B51 /* UserModel.swift in Sources */, F99A8A421A99CEF500DFD19D /* Location.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -275,6 +284,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 700620281DBE0EE000065B51 /* AutoCompletionTextProtocol.swift in Sources */, F96E31A01A98DC36001DCEBF /* AutocompleteTextfieldSwiftTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -349,6 +359,7 @@ ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 2.3; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -384,6 +395,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 8.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; + SWIFT_VERSION = 2.3; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; @@ -395,11 +407,13 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; ENABLE_BITCODE = NO; + GCC_GENERATE_TEST_COVERAGE_FILES = YES; INFOPLIST_FILE = AutocompleteTextfieldSwift/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = mnbayan.AutocompleteTextfieldSwift; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 2.3; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -410,11 +424,13 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; ENABLE_BITCODE = NO; + GCC_GENERATE_TEST_COVERAGE_FILES = YES; INFOPLIST_FILE = AutocompleteTextfieldSwift/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = mnbayan.AutocompleteTextfieldSwift; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 2.3; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; @@ -435,6 +451,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "codefun.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 2.3; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AutocompleteTextfieldSwift.app/AutocompleteTextfieldSwift"; }; name = Debug; @@ -451,6 +468,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "codefun.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 2.3; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AutocompleteTextfieldSwift.app/AutocompleteTextfieldSwift"; }; name = Release; diff --git a/AutocompleteTextfieldSwift/AutoCompleteTextField/AutoCompleteTextField.swift b/AutocompleteTextfieldSwift/AutoCompleteTextField/AutoCompleteTextField.swift index a49cf03..910e807 100644 --- a/AutocompleteTextfieldSwift/AutoCompleteTextField/AutoCompleteTextField.swift +++ b/AutocompleteTextfieldSwift/AutoCompleteTextField/AutoCompleteTextField.swift @@ -15,7 +15,7 @@ public class AutoCompleteTextField:UITextField { /// Holds the collection of attributed strings private lazy var attributedAutoCompleteStrings = [NSAttributedString]() /// Handles user selection action on autocomplete table view - public var onSelect:(String, NSIndexPath)->() = {_,_ in} + public var onSelect:(AutoCompletionTextProtocol, NSIndexPath)->() = {_,_ in} /// Handles textfield's textchanged public var onTextChange:(String)->() = {_ in} @@ -48,8 +48,8 @@ public class AutoCompleteTextField:UITextField { redrawTable() } } - /// The strings to be shown on as suggestions, setting the value of this automatically reload the tableview - public var autoCompleteStrings:[String]?{ + /// The models to be shown on as suggestions, setting the value of this automatically reload the tableview + public var autoCompleteModels:[AutoCompletionTextProtocol]?{ didSet{ reload() } } @@ -82,8 +82,8 @@ public class AutoCompleteTextField:UITextField { autoCompleteAttributes = [NSForegroundColorAttributeName:UIColor.blackColor()] autoCompleteAttributes![NSFontAttributeName] = UIFont.boldSystemFontOfSize(12) self.clearButtonMode = .Always - self.addTarget(self, action: "textFieldDidChange", forControlEvents: .EditingChanged) - self.addTarget(self, action: "textFieldDidEndEditing", forControlEvents: .EditingDidEnd) + self.addTarget(self, action: #selector(AutoCompleteTextField.textFieldDidChange), forControlEvents: .EditingChanged) + self.addTarget(self, action: #selector(AutoCompleteTextField.textFieldDidEndEditing), forControlEvents: .EditingDidEnd) } private func setupAutocompleteTable(view:UIView){ @@ -116,11 +116,16 @@ public class AutoCompleteTextField:UITextField { attributedAutoCompleteStrings.removeAll(keepCapacity: false) } - if let autoCompleteStrings = autoCompleteStrings, let autoCompleteAttributes = autoCompleteAttributes { - for i in 0.. Void in self.autoCompleteTableView?.hidden = self.hidesWhenEmpty! ? self.text!.isEmpty : false }) @@ -150,7 +155,7 @@ public class AutoCompleteTextField:UITextField { extension AutoCompleteTextField: UITableViewDataSource, UITableViewDelegate { public func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return autoCompleteStrings != nil ? (autoCompleteStrings!.count > maximumAutoCompleteCount ? maximumAutoCompleteCount : autoCompleteStrings!.count) : 0 + return autoCompleteModels != nil ? (autoCompleteModels!.count > maximumAutoCompleteCount ? maximumAutoCompleteCount : autoCompleteModels!.count) : 0 } public func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { @@ -160,13 +165,16 @@ extension AutoCompleteTextField: UITableViewDataSource, UITableViewDelegate { cell = UITableViewCell(style: .Default, reuseIdentifier: cellIdentifier) } + let modelObject = autoCompleteModels![indexPath.row] as AutoCompletionTextProtocol + if enableAttributedText{ cell?.textLabel?.attributedText = attributedAutoCompleteStrings[indexPath.row] } else{ cell?.textLabel?.font = autoCompleteTextFont cell?.textLabel?.textColor = autoCompleteTextColor - cell?.textLabel?.text = autoCompleteStrings![indexPath.row] + + cell?.textLabel?.text = modelObject.autocompletionText() } cell?.contentView.gestureRecognizers = nil @@ -174,11 +182,10 @@ extension AutoCompleteTextField: UITableViewDataSource, UITableViewDelegate { } public func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { - let cell = tableView.cellForRowAtIndexPath(indexPath) - if let selectedText = cell?.textLabel?.text { - self.text = selectedText - onSelect(selectedText, indexPath) + if let modelObject = autoCompleteModels![indexPath.row] as AutoCompletionTextProtocol? { + self.text = modelObject.autocompletionText() + onSelect(modelObject, indexPath) } dispatch_async(dispatch_get_main_queue(), { () -> Void in @@ -187,13 +194,13 @@ extension AutoCompleteTextField: UITableViewDataSource, UITableViewDelegate { } public func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) { - if cell.respondsToSelector("setSeparatorInset:"){ + if cell.respondsToSelector(Selector("setSeparatorInset:")){ cell.separatorInset = autoCompleteSeparatorInset } - if cell.respondsToSelector("setPreservesSuperviewLayoutMargins:"){ + if cell.respondsToSelector(Selector("setPreservesSuperviewLayoutMargins:")){ cell.preservesSuperviewLayoutMargins = false } - if cell.respondsToSelector("setLayoutMargins:"){ + if cell.respondsToSelector(Selector("setLayoutMargins:")){ cell.layoutMargins = autoCompleteSeparatorInset } } diff --git a/AutocompleteTextfieldSwift/AutoCompleteTextField/AutoCompletionTextProtocol.swift b/AutocompleteTextfieldSwift/AutoCompleteTextField/AutoCompletionTextProtocol.swift new file mode 100644 index 0000000..ad9fdb2 --- /dev/null +++ b/AutocompleteTextfieldSwift/AutoCompleteTextField/AutoCompletionTextProtocol.swift @@ -0,0 +1,23 @@ +// +// AutoCompletionTextProtocol.swift +// AutocompleteTextfieldSwift +// +// Created by Mohshin Shah on 24/10/2016. +// Copyright © 2016 mnbayan. All rights reserved. +// + +import Foundation + +/** + Enables an model object to be used in AutoCompletion of UITextField. + */ + +public protocol AutoCompletionTextProtocol { + + /** + Returns the autocompletion text + - returns: Model Auto Completion Text. + */ + func autocompletionText() -> String + +} diff --git a/AutocompleteTextfieldSwift/Base.lproj/Main.storyboard b/AutocompleteTextfieldSwift/Base.lproj/Main.storyboard index a532946..aeedac8 100644 --- a/AutocompleteTextfieldSwift/Base.lproj/Main.storyboard +++ b/AutocompleteTextfieldSwift/Base.lproj/Main.storyboard @@ -1,7 +1,10 @@ - - + + - + + + + @@ -13,30 +16,39 @@ - + - - - + + - - - + + + + + + - - + + + + + @@ -44,7 +56,7 @@ - + @@ -59,7 +71,6 @@ - diff --git a/AutocompleteTextfieldSwift/Controllers/ViewController.swift b/AutocompleteTextfieldSwift/Controllers/ViewController.swift index 3217175..3362e07 100644 --- a/AutocompleteTextfieldSwift/Controllers/ViewController.swift +++ b/AutocompleteTextfieldSwift/Controllers/ViewController.swift @@ -11,15 +11,9 @@ import MapKit class ViewController: UIViewController { - @IBOutlet weak var mapView: MKMapView! @IBOutlet weak var autocompleteTextfield: AutoCompleteTextField! - private var responseData:NSMutableData? - private var selectedPointAnnotation:MKPointAnnotation? - private var dataTask:NSURLSessionDataTask? - - private let googleMapsKey = "AIzaSyDg2tlPcoqxx2Q2rfjhsAKS-9j0n3JA_a4" - private let baseURLString = "https://maps.googleapis.com/maps/api/place/autocomplete/json" + @IBOutlet weak var modelInfo: UILabel! override func viewDidLoad() { super.viewDidLoad() @@ -28,11 +22,6 @@ class ViewController: UIViewController { handleTextFieldInterfaces() } - override func didReceiveMemoryWarning() { - super.didReceiveMemoryWarning() - // Dispose of any resources that can be recreated. - } - private func configureTextField(){ autocompleteTextfield.autoCompleteTextColor = UIColor(red: 128.0/255.0, green: 128.0/255.0, blue: 128.0/255.0, alpha: 1.0) autocompleteTextfield.autoCompleteTextFont = UIFont(name: "HelveticaNeue-Light", size: 12.0)! @@ -50,75 +39,28 @@ class ViewController: UIViewController { private func handleTextFieldInterfaces(){ autocompleteTextfield.onTextChange = {[weak self] text in if !text.isEmpty{ - if let dataTask = self?.dataTask { - dataTask.cancel() - } - self?.fetchAutocompletePlaces(text) + self?.fetchAutocompleteModels(text) } } - autocompleteTextfield.onSelect = {[weak self] text, indexpath in - Location.geocodeAddressString(text, completion: { (placemark, error) -> Void in - if let coordinate = placemark?.location?.coordinate { - self?.addAnnotation(coordinate, address: text) - self?.mapView.setCenterCoordinate(coordinate, zoomLevel: 12, animated: true) - } - }) + autocompleteTextfield.onSelect = {[weak self] model , indexpath in + + let user = model as! UserModel + self?.modelInfo.text = "User Id: \(user.userId) \nFName: \(user.firstName) \n LastName: \(user.lastName) " } } - - //MARK: - Private Methods - private func addAnnotation(coordinate:CLLocationCoordinate2D, address:String?){ - if let annotation = selectedPointAnnotation{ - mapView.removeAnnotation(annotation) - } - - selectedPointAnnotation = MKPointAnnotation() - selectedPointAnnotation!.coordinate = coordinate - selectedPointAnnotation!.title = address - mapView.addAnnotation(selectedPointAnnotation!) - } - private func fetchAutocompletePlaces(keyword:String) { - let urlString = "\(baseURLString)?key=\(googleMapsKey)&input=\(keyword)" - let s = NSCharacterSet.URLQueryAllowedCharacterSet().mutableCopy() as! NSMutableCharacterSet - s.addCharactersInString("+&") - if let encodedString = urlString.stringByAddingPercentEncodingWithAllowedCharacters(s) { - if let url = NSURL(string: encodedString) { - let request = NSURLRequest(URL: url) - dataTask = NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in - if let data = data{ - - do{ - let result = try NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments) - - if let status = result["status"] as? String{ - if status == "OK"{ - if let predictions = result["predictions"] as? NSArray{ - var locations = [String]() - for dict in predictions as! [NSDictionary]{ - locations.append(dict["description"] as! String) - } - dispatch_async(dispatch_get_main_queue(), { () -> Void in - self.autocompleteTextfield.autoCompleteStrings = locations - }) - return - } - } - } - dispatch_async(dispatch_get_main_queue(), { () -> Void in - self.autocompleteTextfield.autoCompleteStrings = nil - }) - } - catch let error as NSError{ - print("Error: \(error.localizedDescription)") - } - } - }) - dataTask?.resume() + private func fetchAutocompleteModels(keyword:String) { + + var modelsArray = [AutoCompletionTextProtocol]() + for i in 0...5 { + + let model = UserModel(userId: "\(i)", firstName: "User\(i)", middleName: "", lastName: "Shah") + modelsArray.append(model) } + + self.autocompleteTextfield.autoCompleteModels = modelsArray } - } } diff --git a/AutocompleteTextfieldSwift/UserModel.swift b/AutocompleteTextfieldSwift/UserModel.swift new file mode 100644 index 0000000..03745b3 --- /dev/null +++ b/AutocompleteTextfieldSwift/UserModel.swift @@ -0,0 +1,46 @@ +// +// UserModel.swift +// AutocompleteTextfieldSwift +// +// Created by Mohshin Shah on 24/10/2016. +// Copyright © 2016 mnbayan. All rights reserved. +// + +import Foundation + + +public class UserModel: AutoCompletionTextProtocol { + + /// The user id. + public let userId: String + + /// The user's first name. + public let firstName: String + + /// The user's middle name. + public let middleName: String + + /// The user's last name. + public let lastName: String + + public init(userId: String, + firstName: String? = nil, + middleName: String? = nil, + lastName: String? = nil) { + self.userId = userId + self.firstName = firstName! + self.middleName = middleName! + self.lastName = lastName! + } + + /** + Provides the text to be used in auto completion + - returns: Autocompletion Text. + */ + + public func autocompletionText() -> String { + + return "\(self.firstName) \(self.lastName)" + } + +}