KingTim KingTim -4 years ago 127
Swift Question

Setting data to a class variable (from Google Places API)

Using the Google Places API I can search the map for a place and get info about it (for example website), using this function, called from a Search button in the navigation bar

navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Search", style: .plain, target: self, action: #selector(pickPlace))
:

func pickPlace() {
let center = CLLocationCoordinate2D(latitude: 40.708637, longitude: -74.014839)
let northEast = CLLocationCoordinate2D(latitude: center.latitude + 0.001, longitude: center.longitude + 0.001)
let southWest = CLLocationCoordinate2D(latitude: center.latitude - 0.001, longitude: center.longitude - 0.001)
let viewport = GMSCoordinateBounds(coordinate: northEast, coordinate: southWest)
let config = GMSPlacePickerConfig(viewport: viewport)
let placePicker = GMSPlacePicker(config: config)

placePicker.pickPlace(callback: {(place, error) -> Void in
if let error = error {
print("Pick Place error: \(error.localizedDescription)")
return
}

if let place = place {
// Set place to class variable selectedPlace
self.selectedPlace = place
// Add marker & move camera to new place
if self.selectedPlace != nil {
let cam = GMSCameraPosition.camera(withTarget: (self.selectedPlace?.coordinate)!, zoom: 18)
let mapView = GMSMapView.map(withFrame: CGRect.zero, camera: cam)
let newPlaceMarker = GMSMarker(position: (self.selectedPlace?.coordinate)!)
newPlaceMarker.map = mapView
self.navigationItem.title = self.selectedPlace?.name
print(self.selectedPlace?.website)
newPlaceMarker.title = self.selectedPlace?.name
self.view = mapView
}

} else {
self.navigationItem.title = "No place selected"
}
})
}


Inside
if let place = place
I attempt to set place to a class variable called
var selectedPlace: GMSPlace?
by using
self.selectedPlace = place
. However, when I try to print, for example
print(self.selectedPlace?.website)
, it is nil - so I think I'm not setting the variable correctly, however I'm not sure why.

How can I correctly set
place
from the
pickPlace
function to my class variable
selectedPlace
so I can use it around my app?

EDIT: To show what I'm trying to use the class variable for

I'm trying to get my custom info window to appear on a user-searched marker, and not only on my default markers. This is my customInfoWindow function - note the "default" condition is where the window should appear if the marker is user-searched, and where I'm trying to use
self.selectedPlace?
values like
name


func mapView(_ mapView: GMSMapView, markerInfoWindow marker: GMSMarker) -> UIView? {

let customInfoWindow = Bundle.main.loadNibNamed("CustomInfoWindow", owner: self, options: nil)?[0] as! CustomInfoWindow
let placeName = marker.title!

switch placeName {
case "TGI Friday's":
customInfoWindow.nameLbl.text = "TGI Friday's"
customInfoWindow.detailLabel.text = "Thoroughly Average Chain Restaurant"
customInfoWindow.placeImage.image = UIImage(named: "fridays")
self.navigationItem.title = "TGI Friday's"
case "George's":
customInfoWindow.nameLbl.text = "George's"
customInfoWindow.detailLabel.text = "Old School Diner"
customInfoWindow.placeImage.image = UIImage(named: "georges")
self.navigationItem.title = "George's"
case "Reserve Cut":
customInfoWindow.nameLbl.text = "Reserve Cut"
customInfoWindow.detailLabel.text = "Kosher Steakhouse"
customInfoWindow.placeImage.image = UIImage(named: "reserveCut")
self.navigationItem.title = "Reserve Cut"
case "O'Hara's":
customInfoWindow.nameLbl.text = "O'Hara's"
customInfoWindow.detailLabel.text = "Irish Pub"
customInfoWindow.placeImage.image = UIImage(named: "oharas")
self.navigationItem.title = "O'Hara's"
case "Bill's Bar & Burger":
customInfoWindow.nameLbl.text = "Bill's Bar & Burger"
customInfoWindow.detailLabel.text = "Bar founded by Bill that also has burgers"
customInfoWindow.placeImage.image = UIImage(named: "bills")
self.navigationItem.title = "Bill's Bar & Burger"
default:
customInfoWindow.nameLbl.text = self.selectedPlace?.name
customInfoWindow.placeImage.image = UIImage(named: "noImage")
self.navigationItem.title = self.selectedPlace?.name
}

return customInfoWindow
}


Then once I get the info window to appear, I'd like to tap on it and be brought to the website - again, the default condition is where I'm trying to use the
self.selectedPlace?
values:

func mapView(_ mapView: GMSMapView, didTapInfoWindowOf marker: GMSMarker) {

let placeName = marker.title!

switch placeName {
case "George's":
if let georgesUrl = URL(string: "http://www.georges-ny.com") {
self.webView.load(URLRequest(url: georgesUrl))
}
case "TGI Friday's":
if let fridaysUrl = URL(string: "https://www.tgifridays.com") {
self.webView.load(URLRequest(url: fridaysUrl))
}
case "Reserve Cut":
if let rcUrl = URL(string: "http://reservecut.com") {
self.webView.load(URLRequest(url: rcUrl))
}
case "Bill's Bar & Burger":
if let billsUrl = URL(string: "http://www.billsbarandburger.com") {
self.webView.load(URLRequest(url: billsUrl))
}
case "O'Hara's":
if let oharasUrl = URL(string: "http://www.oharaspubnyc.com") {
self.webView.load(URLRequest(url: oharasUrl))
}
default:
// user-selected place
if let site = self.selectedPlace?.website {
self.webView.load(URLRequest(url: site))
}
}

webView.allowsBackForwardNavigationGestures = false
self.view = webView


// return to map
var backButton = UIImage(named: "back")
backButton = backButton?.withRenderingMode(UIImageRenderingMode.alwaysOriginal)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(image: backButton, style: UIBarButtonItemStyle.plain, target: self, action: #selector(handleReturn))
navigationItem.title = "Restaurant Webpage"
}

Answer Source

Your problem is that you are creating a new map view in your callback closure rather than adding the place to the existing map view. This new map view is missing all of your original places and it's delegate isn't set to your view controller instance, so the delegate methods aren't called.

When you create the map view you should store it in an instance property and add the new place to that map view:

 if self.selectedPlace != nil {
     let cam = GMSCameraPosition.camera(withTarget: (self.selectedPlace?.coordinate)!, zoom: 18)
     let newPlaceMarker = GMSMarker(position: (self.selectedPlace?.coordinate)!)
     newPlaceMarker.map = self.mapView
     self.mapView.camera = cam

     self.navigationItem.title = self.selectedPlace?.name
     print(self.selectedPlace?.website)
     newPlaceMarker.title = self.selectedPlace?.name
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download