Search code examples
iosswiftpush-notificationcore-locationunnotificationtrigger

Trigger notification when moving to another city


I want to trigger a notification everytime the current city changes based on didUpdateLocations:

func locationManager(_ manager: CLLocationManager,  didUpdateLocations locations: [CLLocation]) {
    let lastLocation = locations.last!
    updateLocation(location: lastLocation)
}

So here I would compare if the city has changed and send a push notification based on that. How could I do this?

func updateLocation(location: CLLocation) {
    fetchCityAndCountry(from: location) { city, country, error in
        guard let city = city, let country = country, error == nil else { return }
        self.locationLabel.text = city + ", " + country
        if(city !== previousCity){
          //Send push notification
        }
    }
}

I know I can trigger it based on location with a range but that's not specific enough for me.


Solution

  • Consider using the reverse geocoder api, it resolves CLLocation to CLPlacemark, which contains country name, city name and even street name in the language (local) you prefer. So basically, your code will be like.

    func updateLocation(location: CLLocation) {
      CLGeocoder().reverseGeocodeLocation(location, completionHandler: {(placemarks, error)-> Void in
            if error != nil {
                return
            }
    
            if placemarks!.count > 0 {
                let placemark = placemarks![0]
                print("Address: \(placemark.name!) \(placemark.locality!), \(placemark.administrativeArea!) \(placemark.postalCode!)")
                if placemark.locality! !== previousCity) {
                    // Send push notification
                }
            } else {
                print("No placemarks found.")
            }
        })
    }
    

    EDIT 2

    As for sending the notification, instead of using UNLocationNotificationTrigger, just use the "normal trigger" - UNTimeIntervalNotificationTrigger.

        let notification = UNMutableNotificationContent()
        notification.title = "Notification"
        notification.subtitle = "Subtitle"
        notification.body = "body"
    
        let notificationTrigger = UNTimeIntervalNotificationTrigger(timeInterval: 0, repeats: false)
        let request = UNNotificationRequest(identifier: "notification1", content: notification, trigger: notificationTrigger)
        UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
    

    Edit 1

    You don't want to call the geocoder very often, so you should check the distance between the current location and the last "checkpoint", only when it's big enough will you call the geocoder, otherwise it would be a waste.

    BTW, the notification will be send from the phone itself, no server or APNS involved, this is called a local notification, not push notification.