How to add google places autocomplete to xcode with swift (tutorial) - ios

I want to add google places autocomplete to xcode with swift, so users can search on a city and press enter, so should the app show that city on the map.
I´m using google maps, so it has to be connected to that map and the search bar would i like to have in the navi-bar (just above the map)
Does anyone know a good tutorial to do that??

For Swift 3:
1- Select your podfile and type : pod 'GooglePlaces'
2- In the appDelegate, add your API Key :
GMSPlacesClient.provideAPIKey("YOUR KEY") (Import the GooglePlaces)
3- Use this code in your viewController that contains the googleMap:
// This code snippet demonstrates adding a
// full-screen Autocomplete UI control
import UIKit
import GooglePlaces
class ViewController: UIViewController {
// TODO: Add a button to Main.storyboard to invoke onLaunchClicked.
// Present the Autocomplete view controller when the button is pressed.
#IBAction func onLaunchClicked(sender: UIButton) {
let acController = GMSAutocompleteViewController()
acController.delegate = self
present(acController, animated: true, completion: nil)
}
}
extension ViewController: GMSAutocompleteViewControllerDelegate {
// Handle the user's selection.
func viewController(_ viewController: GMSAutocompleteViewController, didAutocompleteWith place: GMSPlace) {
print("Place name: \(place.name)")
print("Place address: \(place.formattedAddress)")
print("Place attributions: \(place.attributions)")
dismiss(animated: true, completion: nil)
}
func viewController(_ viewController: GMSAutocompleteViewController, didFailAutocompleteWithError error: Error) {
// TODO: handle the error.
print("Error: \(error)")
dismiss(animated: true, completion: nil)
}
// User cancelled the operation.
func wasCancelled(_ viewController: GMSAutocompleteViewController) {
print("Autocomplete was cancelled.")
dismiss(animated: true, completion: nil)
}
}

Not exactly tutorials, but there are a few resources on Github, with people providing libraries and code samples to achieve what you're asking for.
SPGooglePlacesAutocomplete (https://github.com/spoletto/SPGooglePlacesAutocomplete) is very popular and has many features, but it's written in Objective-C
iOS Google Places Autocomplete (https://github.com/watsonbox/ios_google_places_autocomplete) is more recent, written in Swift, and also contains some examples.
lots of others...
Even without proper tutorials, you can still check out these libraries and understand how their code works to get some inspiration if you want to write your own components.
As a sidetone, Google also has this page, but it's not a dedicated tutorial for iOS apps, just some useful explanations of how their API works: https://developers.google.com/places/documentation/autocomplete#examples

You can try one for wrapper to implement Autocompletion for Place API with Google:
https://github.com/mrugrajsinh/MVAutocompletePlaceSearchTextField
Its very simple drop-in control and subclass of UITextField so using by binding Class with simple UITextField you can achive Auto completion dropdown similar as Uber and many popular app does.

Here's a tutorial I came across which is based on my ios_google_places_autocomplete code.
#Frederik: If you've had a problem with the library, please create an issue describing it.

please check this one 110% work.
http://sweettutos.com/2015/09/30/how-to-use-the-google-places-autocomplete-api-with-google-maps-sdk-on-ios/

Use this latest repo. with swift 2.0
Just download zip file of project and open pod file and write pod 'GoogleMaps' and save it open terminal and install pod.
Enjoy!!!
RKAutoCompletePlaceSearch

Since the question was asked, Google has added UI elements to the iOS SDK for this sort of workflow. Check out the documentation.

Simple and lightweight solution for Swift users !
I also created a library to make these simple request without including any framework of third party library. You can also maintain cache for Autocomplete with the library.
To use to library follow these steps : -
step-1 Import GoogleApiHelper into your project.
step-2 Initialise GoogleApiHelper
GoogleApi.shared.initialiseWithKey("API_KEY")
step-3 Call the methods
var input = GInput()
input.keyword = "San francisco"
GoogleApi.shared.callApi(input: input) { (response) in
if let results = response.data as? [GApiResponse.Autocomplete], response.isValidFor(.autocomplete) {
//Enjoy the Autocomplete Api
} else { print(response.error ?? "ERROR") }
}
You can find the library here

Related

Stripe error : submitTokenToBackend error, unresolved identifier error

I am working on a stripe project on iOS. I followed the start guide on stripe website for a primary test.
For iOS app, their SDK had a built-in addCardViewController. So I just copy and paste the code to my ViewController file. However, now I am having an error which is, an unresolved identifier submitToBackEnd.
Can anyone tell me what the possible problem is?
Below I have added the code which I used:
func addCardViewController(_ addCardViewController: STPAddCardViewController, didCreateToken token: STPToken, completion: #escaping STPErrorBlock) {
submitTokenToBackend(token, completion: { (error: Error?) in
if let error = error {
// Show error in add card view controller
completion(error)
}
else {
// Notify add card view controller that token creation was handled successfully
completion(nil)
// Dismiss add card view controller
dismiss(animated: true)
}
})
}
It's because you're missing the submitTokenToBackend function declaration. The Stripe documentation assumes you're writing it yourself. (it's mentioned here after the code block https://stripe.com/docs/mobile/ios/custom#stpapiclient--stpcardparams)
The implementation varies greatly depending on what you use to send requests from your App to your backend. It's not exactly the same but you can look at this part of the Standard Example to see how it roughly works:
https://github.com/stripe/stripe-ios/blob/master/Example/Standard%20Integration%20(Swift)/MyAPIClient.swift#L25

IOS swift how to know when activityViewController has been successfully used

I have a tableView that utilizes the UIActivityViewController so users can share content on other 3rd party networks Facebook, twitter, text message etc. I have a function called IncreaseShareByOne() and it's purpose is to count the number of times that something has been shared . My problem is that right now that function fires of every time the UIActivityViewController is clicked . Is there someway that I can find out if a user really shared something so that I can use that function correctly ? becomes sometimes you open the UIActivityViewController and decide not to share anything so I want to catch and not use that function. I am new to swift and am using version 3 .
func sharedShareAction(controller: UIViewController, sender: UIButton) {
controller.present(activityViewController,animated: true,completion: nil)
IncreaseShareByOne()
}
You can add a completion handler to your UIActivityViewController. In the completion handler, check whether the user submitted using the completed value. You'll probably want to do something like this:
func sharedShareAction(controller: UIViewController, sender: UIButton) {
controller.present(activityViewController,animated: true, completion: nil)
activityViewController.completionWithItemsHandler = { activity, completed, items, error in
if !completed {
// handle task not completed
return
}
IncreaseShareByOne()
}
}
Check the API docs for more info.

How to get more results from CoreLocations geocodeAddressString?

I have an application that allows the user to enter some an address, I then want to basically serve up a list of possible addresses that they might be referring to and so that I can use it in MapKit readable form.
My current approach is so:
extension ViewController: UITextFieldDelegate{
func textFieldDidEndEditing(_ textField: UITextField) {
CLGeocoder().geocodeAddressString(textField.text!, completionHandler: {(placemarks: [CLPlacemark]?, error: Error?) -> Void in
if let placemarks = placemarks{
//send placemarks to table view
//however, placemarks only contains one element
//(even when textfield contains very generic text)
} else{ }
})
}
}
Does anyone know how to get more results? Using Apple's Map app and they load 15 results from entering just 4 numbers, how can I get my app to display this many results? Is Apple using something other than coreLocation to bring up possible locations?
EDIT: I think the Google Places API for iOS should help you get what you need. I do not believe Apple has an equivalent API (unless you want plain language searches a la MKLocalSearchRequest).

Nearby Bluetooth devices using Swift 3.0

I'm looking for a way to programmatically list any nearby Bluetooth devices (discoverable) that my device finds. I have not been able to find any information or tutorials regarding performing this call in Swift 3.0. This Q-A post discusses finding these devices using Swift 1.0 and building in Xcode 6, rather than the latest version 8.
I did my best to try to make my code into the 3.0 Syntax from the 1.0, but while running the following code, nothing is returned in the Playground:
import Cocoa
import IOBluetooth
import PlaygroundSupport
class BlueDelegate : IOBluetoothDeviceInquiryDelegate {
func deviceInquiryComplete(_ sender: IOBluetoothDeviceInquiry, error: IOReturn, aborted: Bool) {
aborted
print("called")
let devices = sender.foundDevices()
for device : Any? in devices! {
if let thingy = device as? IOBluetoothDevice {
thingy.getAddress()
}
}
}
}
var delegate = BlueDelegate()
var inquiry = IOBluetoothDeviceInquiry(delegate: delegate)
inquiry?.start()
PlaygroundPage.current.needsIndefiniteExecution = true
Using IOBluetooth the Correct Way
The following code works flawlessly in Xcode Version 8.2.1 (8C1002), Swift 3.0. There are a few lines that aren't required, such as the entire method of deviceInquiryStarted.
Update: These usages still work as of Xcode 9.2 (9B55) and Swift 4.
Playground
import Cocoa
import IOBluetooth
import PlaygroundSupport
class BlueDelegate : IOBluetoothDeviceInquiryDelegate {
func deviceInquiryStarted(_ sender: IOBluetoothDeviceInquiry) {
print("Inquiry Started...")
//optional, but can notify you when the inquiry has started.
}
func deviceInquiryDeviceFound(_ sender: IOBluetoothDeviceInquiry, device: IOBluetoothDevice) {
print("\(device.addressString!)")
}
func deviceInquiryComplete(_ sender: IOBluetoothDeviceInquiry!, error: IOReturn, aborted: Bool) {
//optional, but can notify you once the inquiry is completed.
}
}
var delegate = BlueDelegate()
var ibdi = IOBluetoothDeviceInquiry(delegate: delegate)
ibdi?.updateNewDeviceNames = true
ibdi?.start()
PlaygroundPage.current.needsIndefiniteExecution = true
Project-Application Usage
import Cocoa
import IOBluetooth
import ...
class BlueDelegate : IOBluetoothDeviceInquiryDelegate {
func deviceInquiryStarted(_ sender: IOBluetoothDeviceInquiry) {
print("Inquiry Started...")
}
func deviceInquiryDeviceFound(_ sender: IOBluetoothDeviceInquiry, device: IOBluetoothDevice) {
print("\(device.addressString!)")
}
}
//other classes here:
//reference the following outside of any class:
var delegate = BlueDelegate()
var ibdi = IOBluetoothDeviceInquiry(delegate: delegate)
//refer to these specifically inside of any class:
ibdi?.updateNewDeviceNames = true
ibdi?.start() //recommended under after an action-button press.
Explanation
The issue I was originally faced with was trying to access the information as the inquiry was still in process.
When I accessed it, under many different occasions my playground would hang and I would be forced to force quit both Xcode.app, and com.apple.CoreSimulator.CoreSimulatorService from the Activity Monitor. I lead myself to believe that this was just a Playground bug, only to learn that my application would crash once the inquiry finished.
As Apple's API Reference states:
Important Note: DO NOT perform remote name requests on devices from delegate methods or while this object is in use. If you wish to do your own remote name requests on devices, do them after you have stopped this object. If you do not heed this warning, you could potentially deadlock your process.
Which entirely explained my issue. Rather than directly asking for the IOBluetoothDevice information from the sender.foundDevices() method (which I believe may not have been updating..?) I simply used the parameters built into the function to mention that it was indeed an IOBluetoothDevice object, and simply to ask for that information to be printed.
Final Note
I hope that this Q/A I've created helps others in need when using IOBluetooth in Swift. The lack of any tutorials and the high amounts of outdated, Objective-C code made finding this information very challenging. I'd like to thank #RobNapier for the support on trying to find the answer to this riddle in the beginning. I'd also like to thank NotMyName for the reply on my post on the Apple Developer Forums.
I will be exploring the usage of this in an iOS device more sooner than later!

Cannot call value of non-function type UIApplication when trying to open google maps URL

I'm new to swift programming and I stumbled upon a problem which can't seem to find a solution after searching the web.
What i'm trying to do is when a button is tapped in my application I want the Google maps app to launch but after implementing the code I get the error: Cannot call value of non-function type UIApplication
Am I missing something?
import UIKit
import GoogleMaps
class MapDisplayViewController: UIViewController, GMSMapViewDelegate, CLLocationManagerDelegate, UIApplicationDelegate {
#IBOutlet weak var openDirections: UIButton!
#IBAction func openMapsDirection(_ sender: UIButton!) {
if (UIApplication.sharedApplication().canOpenURL(NSURL(string:"comgooglemaps://")!)) {
UIApplication.sharedApplication().openURL(NSURL(string:
"comgooglemaps://?center=40.765819,-73.975866&zoom=14&views=traffic")!)
} else {
print("Can't use comgooglemaps://");
}
}
}
In Swift 3 sharedApplication() has been replaced with a property called shared.
Try updating your code:
if (UIApplication.shared.canOpenURL(NSURL(string:"comgooglemaps://")!)) {
UIApplication.shared.openURL(NSURL(string:
"comgooglemaps://?center=40.765819,-73.975866&zoom=14&views=traffic")!)
} else {
print("Can't use comgooglemaps://");
}
"comgooglemaps:// and comgooglemaps-x-callback:// - These schemes allow you to launch the Google Maps app for iOS and perform one of several actions"
Please make sure that your device already installed Google Maps app.
https://developers.google.com/maps/documentation/ios-sdk/urlscheme
Hope this will help you.

Resources