From 7ee084cbc5fe863de079b9f7b8334d0d290582a6 Mon Sep 17 00:00:00 2001 From: Mohshin Shah Date: Mon, 24 Oct 2016 17:18:58 +0530 Subject: [PATCH] Using Model Objects (Not only Strings) for the auto completion --- .DS_Store | Bin 8196 -> 8196 bytes .../project.pbxproj | 18 ++++ .../AutoCompleteTextField.swift | 47 ++++++---- .../AutoCompletionTextProtocol.swift | 23 +++++ .../Base.lproj/Main.storyboard | 39 +++++--- .../Controllers/ViewController.swift | 88 +++--------------- AutocompleteTextfieldSwift/UserModel.swift | 46 +++++++++ 7 files changed, 154 insertions(+), 107 deletions(-) create mode 100644 AutocompleteTextfieldSwift/AutoCompleteTextField/AutoCompletionTextProtocol.swift create mode 100644 AutocompleteTextfieldSwift/UserModel.swift diff --git a/.DS_Store b/.DS_Store index 7aee18b66c302ceb55ca191af7d742ebc6cf7fc0..7227ea638035d47615b3a403688cb54f394841b3 100644 GIT binary patch delta 64 zcmZp1XmQx^N{H#6z~l)+K76_PE-ophCCLm7SBz)=nA|7i2NX&{6Po-%n3st;VDo=r GRvrK%-WUo1 delta 64 zcmZp1XmQx^N{Gqy%j5|{K76_PE-ophCCLm7m*-XTOzso%0}7>}2~GYW%*(`7u=&3* GD-Qq() = {_,_ 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)" + } + +}