Skip to content

Instantly share code, notes, and snippets.

@AdieOlami
Created June 25, 2019 10:21
Show Gist options
  • Save AdieOlami/201ddb5b99c08a5f1316b0b91b9b994a to your computer and use it in GitHub Desktop.
Save AdieOlami/201ddb5b99c08a5f1316b0b91b9b994a to your computer and use it in GitHub Desktop.
GooglePlace Autocomplete
import UIKit
import GooglePlaces
class PlaceSearchField: UITextField, UITextFieldDelegate {
//MARK: - PROPERTIES
/// Instance of autoCompleteTableView
fileprivate var autoCompleteTableView: UITableView?
/// Gives the array of autoCompletePlacesData
open var autoCompletePlacesData = [String]()
/// Gives the selected place and indexPath
open var selectedPlace: ((String, IndexPath) -> Void)?
/// Font for the places data
open var autoCompleteTextFont = UIFont.systemFont(ofSize: 12)
/// Color of the places data
open var autoCompleteTextColor = UIColor.black
/// Used to set the height of cell for each suggestions
open var autoCompleteCellHeight: CGFloat = 44.0
/// The maximum visible suggestion
open var maxAutoCompleteDataCount = 5
/// Used to set your own preferred separator inset
open var autoCompleteSeparatorInset = UIEdgeInsets.zero
/// Hides autoCompleteTableView after selecting a place
open var hidesWhenSelected = true
/// Shows autoCompletePlacesData with formatting
open var highLightTypeTextedEnabled: Bool?
/// Define attributes for highlighted text
open var highLightTypeTextedAttributes: [NSAttributedString.Key: Any]?
/// Hides autoCompleteTableView when the textfield is empty
open var hidesWhenEmpty: Bool? {
didSet {
DispatchQueue.main.async {
self.autoCompleteTableView?.isHidden = self.hidesWhenEmpty!
}
}
}
/// The autoCompleteTableView height
open var autoCompleteTableHeight:CGFloat?{
didSet {
redrawTable()
}
}
/// this is the x margin for table view from textfield
open var autoCompleteTableMargin = CGFloat()
// MARK: - INIT FUNCTIONS
public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
setupAutocompleteTable(superview!)
}
public override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
translatesAutoresizingMaskIntoConstraints = false
// setupAutocompleteTable(superview!)
if let newSuperviews = superview {
setupAutocompleteTable(newSuperviews)
}
}
open override func awakeFromNib() {
super.awakeFromNib()
commonInit()
setupAutocompleteTable(superview!)
}
override func layoutSubviews() {
super.layoutSubviews()
commonInit()
setupAutocompleteTable(superview!)
}
// open override func willMove(toSuperview newSuperview: UIView?) {
// super.willMove(toSuperview: newSuperview)
// commonInit()
// setupAutocompleteTable(newSuperview!)
// }
public override func willMove(toSuperview newSuperview: UIView?) {
super.willMove(toSuperview: newSuperview)
commonInit()
if let newSuperviews = newSuperview {
setupAutocompleteTable(newSuperviews)
}
}
fileprivate func commonInit(){
hidesWhenEmpty = true
highLightTypeTextedEnabled = false
highLightTypeTextedAttributes = [NSAttributedString.Key.font:
UIFont(name: "Helvetica-Bold", size: 12.0)!,
NSAttributedString.Key.foregroundColor: UIColor.white]
self.clearButtonMode = .always
self.addTarget(self, action: #selector(PlaceSearchField.textFieldDidChange), for: .editingChanged)
self.addTarget(self, action: #selector(PlaceSearchField.textFieldDidEndEditing), for: .editingDidEnd)
}
fileprivate func setupAutocompleteTable(_ view: UIView) {
autoCompleteTableMargin = 10.0
// let tableView = UITableView(frame: CGRect(x: self.frame.origin.x + autoCompleteTableMargin/2, y: self.frame.origin.y + self.frame.height, width: (self.frame.width - autoCompleteTableMargin), height: 30.0))
let tableView = UITableView(frame: .zero)
tableView.translatesAutoresizingMaskIntoConstraints = false
// tableView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
// tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
// tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
// tableView.centerXAnchor.cons
// tableView.heightAnchor.constraint(equalToConstant: 30).isActive = true
tableView.dataSource = self
tableView.delegate = self
tableView.rowHeight = autoCompleteCellHeight
// tableView.isHidden = hidesWhenEmpty ?? true
tableView.layer.borderColor = UIColor.lightGray.cgColor
tableView.layer.borderWidth = 0.5
// tableView.layer.zPosition = CGFloat(Float.greatestFiniteMagnitude)
// tableView.backgroundColor = .red
view.addSubview(tableView)
autoCompleteTableView = tableView
autoCompleteTableHeight = 200.0
}
fileprivate func redrawTable() {
if let autoCompleteTableView = autoCompleteTableView, let autoCompleteTableHeight = autoCompleteTableHeight {
var newFrame = autoCompleteTableView.frame
newFrame.size.height = autoCompleteTableHeight
autoCompleteTableView.frame = newFrame
}
}
// MARK: - Private Methods
fileprivate func showHighlightedTypedText(aStr: NSString) -> NSAttributedString {
// highLightTypeTextedAttributes = [NSAttributedString.Key.font.rawValue:
// UIFont(name: "Helvetica-Bold", size: 12.0)!,
// NSAttributedString.Key.foregroundColor: UIColor.white] as? [NSAttributedString.Key.RawValue: AnyObject]
let attrs = [NSAttributedString.Key.foregroundColor: autoCompleteTextColor, NSAttributedString.Key.font: autoCompleteTextFont] as [NSAttributedString.Key: Any]
let range = aStr.range(of: text!, options: .caseInsensitive)
let attString = NSMutableAttributedString(string: aStr as String, attributes: attrs)
attString.addAttributes(highLightTypeTextedAttributes!, range: range)
autoCompleteTextColor = UIColor.gray
return attString
}
// MARK: - AJAutoCompleteTextfieldDelegate
@objc func textFieldDidChange(){
let placesClient = GMSPlacesClient()
placesClient.autocompleteQuery(text!, bounds: nil, filter: nil, callback: { (results, error) in
DispatchQueue.main.async {
self.autoCompletePlacesData.removeAll()
if results != nil {
for result in results!{
self.autoCompletePlacesData.append(result.attributedFullText.string)
}
}
if self.autoCompletePlacesData.count != 0{
self.hidesWhenEmpty = false
if self.autoCompletePlacesData.count < self.maxAutoCompleteDataCount{
self.autoCompleteTableHeight = self.autoCompleteTableView?.contentSize.height
}else{
self.autoCompleteTableHeight = 200
}
self.autoCompleteTableView?.reloadData()
}else{
self.hidesWhenEmpty = true
}
self.autoCompleteTableView?.isHidden = self.hidesWhenEmpty!
}
})
}
@objc func textFieldDidEndEditing() {
autoCompleteTableView?.isHidden = true
}
}
// MARK: - UITableViewDataSource & UITableViewDelegate
extension PlaceSearchField: UITableViewDataSource, UITableViewDelegate {
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return autoCompletePlacesData.count
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellIdentifier = "autocompleteCellIdentifier"
var cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier)
if cell == nil{
cell = UITableViewCell(style: .default, reuseIdentifier: cellIdentifier)
}
if highLightTypeTextedEnabled!{
cell?.textLabel?.attributedText = showHighlightedTypedText(aStr: autoCompletePlacesData[indexPath.row] as NSString)
}else{
cell?.textLabel?.font = autoCompleteTextFont
cell?.textLabel?.textColor = autoCompleteTextColor
cell?.textLabel?.text = autoCompletePlacesData[indexPath.row]
}
cell?.textLabel?.numberOfLines = 0
cell?.contentView.gestureRecognizers = nil
return cell!
}
public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath)
if let selectedText = cell?.textLabel?.text {
self.text = selectedText
self.resignFirstResponder()
selectedPlace!(selectedText, indexPath)
}
DispatchQueue.main.async(execute: { () -> Void in
tableView.isHidden = self.hidesWhenSelected
})
}
public func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if cell.responds(to: #selector(setter: UITableViewCell.separatorInset)){
cell.separatorInset = autoCompleteSeparatorInset
}
if cell.responds(to: #selector(setter: UIView.preservesSuperviewLayoutMargins)){
cell.preservesSuperviewLayoutMargins = false
}
if cell.responds(to: #selector(setter: UIView.layoutMargins)){
cell.layoutMargins = autoCompleteSeparatorInset
}
}
public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return autoCompleteCellHeight
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment