Map Functionalities and Notifications

Final Map Screen

 

After implementing our first version of the map screen, we decided to add a radius picker on the bottom of the map screen to make the user more comfortable to select a radius for the location based notifications. This picker will only be enabled, if the user chose a location with a longpress gesture or if he inserts an address in the search bar which is attached to the navigation bar. The selection of another radius effects the automatic adaptation of the location radius on the screen. In addition, a simple tap on the pin shows a popup that includes either the street name and number if available, or the exact coordinates (Longitude and Latitude) of the selected location.

 

Bildschirmfoto 2016 01 04 um 21.42.35

 

To detect user gestures we used the UIGestureRecognizer classes of Swift. These classes provide a default implementation to detect common gestures like taps, swipes, and long presses. To realize a longpress recognizer, we specified a callback function „longPressGesture“ to receive notifications when the gesture starts, changes, or ends. This recognizer is associated with the mapView in the viewDidLoad - method:

 

override func viewDidLoad() {

 

        super.viewDidLoad()

        let longPress = UILongPressGestureRecognizer(target: self, action: "longPressGesture:")

        longPress.minimumPressDuration = 1.0

        mapView.addGestureRecognizer(longPress)

 

}

 

The longPressGesture function, as shown below, detects the exact location of the user gesture made within the map view. This point can be converted to coordinates (CLLocationCoordinate2D). 

MapKit also provides methods to get address details - if available - from these coordinates. To convert the users input in the search bar to coordinates and to show the street name of an annotation by tapping, we used MapKit’s CLGeocoder class. Therefore, the reverseGeocodeLocation method was important to convert a location from address and an address from a location (coordinates).

 

func longPressGesture(gestureRecognizer:UIGestureRecognizer) {

 

   let touchPoint = gestureRecognizer.locationInView(mapView)

            let newCoord:CLLocationCoordinate2D = mapView.convertPoint(touchPoint, toCoordinateFromView: self.mapView)

            

            //add pin with radius

            addAnnotationWithRadius(newCoord)

            

            if gestureRecognizer.state == UIGestureRecognizerState.Ended {

                let geoCoder = CLGeocoder()

                lastLocation = CLLocation(latitude: newCoord.latitude as CLLocationDegrees, longitude: newCoord.longitude as CLLocationDegrees)

                geoCoder.reverseGeocodeLocation(lastLocation, completionHandler: { (placemarks, error) -> Void in

                    

                    if placemarks != nil {

                       let placeArray = placemarks! as [CLPlacemark]

             

                        var placeMark: CLPlacemark!

                        placeMark = placeArray[0]

                        

                        // Street name and number

                        if let street = placeMark.addressDictionary!["Street"] as? NSString {

                            print(street)

                            self.annotation.subtitle = street as String

                        }

                        else{

                            // Coordinates

                            let lat:Double = (placeMark.location?.coordinate.latitude)!

                            let lon:Double = (placeMark.location?.coordinate.longitude)!

                            self.annotation.subtitle = "LAT: \(lat) LON: \(lon)"

                        }

                    }

                    

                })

            }

}

 

Saved Locations

 

We appended to the bottom of the Add Task Screen a small map view which will only be visible after the user has chosen a location. This view shows the selected location and radius where the location based notification will be triggered when the user enters this region.

 

Bildschirmfoto 2016 01 04 um 21.42.51

 

Notifications

 

Local notifications are a simple way to display information to the user when the app is in the background. For Repeat we implemented two kinds of local notifications. One notifies the user, if a task is expired and another if he enters a given task area.

 

Location Based Notifications

 

To use location based notifications it is necessary to allow Repeat location access. Therefore, the user permission NSLocationAlwaysUsageDescription is essential. It allows the app to access the users location even when he is not using the app. Every time, when a task with an associated location is saved or updated in the database, the method registerUserMonitoring will be called. The LocationManager provides a function startMonitoringForRegion that notifies him if the user is entering this area (didEnterRegion). This location based notfication will only be send if the next countdown is within 24 hours.

 

func registerUserMonitoring(location: Location){

        

        let latitude = location.latitude!.doubleValue

        let  longitude = location.longitude!.doubleValue

        let radius = location.radius!.doubleValue

        

        let monitorRegion = CLCircularRegion(center: CLLocationCoordinate2D(latitude: latitude, longitude: longitude), radius: radius)

        locationManager.startMonitoringForRegion(monitorRegion)

 

}

 

func locationManager(manager: CLLocationManager, didEnterRegion region: CLRegion) {

        

        self.repeatable = self.newRepeatableView.getData()

                

       if self.repeatable.getSecondsToNextCountdown() <= DateHelper.daysToSecond(1) {

            Notifications.setLocationNotification(self.repeatable)

        }

 

}

 

Bildschirmfoto 2016 01 04 um 21.43.16

 

Time Based Notifications

 

A UILocalNotification object specifies a notification that an app can schedule for presentation at a specific date and time (https://developer.apple.com/library/ios/documentation/iPhone/Reference/UILocalNotification_Class/).

Instances of UILocalNotification have a userInfo property ([NSObject : AnyObject]?) that we used to give the notifications unique names with the usage of universally unique identifier (UUID) as shown below. This was important for later modifications of the notification dates if the user resets a task for example. Local notifications are automatically unscheduled after they are fired.

 

    private static func setNotification(fireDate:NSDate, repeatable:Repeatable){

        

        let fireDateOfNotification: NSDate = fireDate

        

        let notification = UILocalNotification()

        notification.timeZone = NSTimeZone.localTimeZone()

        

        notification.alertBody = "A task has been expired!"

        notification.soundName = UILocalNotificationDefaultSoundName

        notification.fireDate = fireDateOfNotification

        notification.userInfo = ["UUID": (repeatable.objectID.persistentStore?.identifier)!]        

        UIApplication.sharedApplication().scheduleLocalNotification(notification)

    }

 

Rate this blog entry:
0
OAuth 2
Start to Implement

Related Posts

 

Comments

No comments made yet. Be the first to submit a comment
Already Registered? Login Here
Guest
Thursday, 19 October 2017

Captcha Image