Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using the new CLVisit in CoreLocation

I didn't find anything talking about CLVisit, so I'm trying to explore the technology by myself.

Does anyone know why it isn't working? All the .plist keys are set and working.

class ViewController: UIViewController,CLLocationManagerDelegate {

var manager:CLLocationManager!

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    manager = CLLocationManager()
    manager.delegate = self
    manager.desiredAccuracy = kCLLocationAccuracyBest
    manager.requestAlwaysAuthorization()
    manager.startMonitoringVisits()


}


func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {

}
func locationManager(manager: CLLocationManager!,
    didVisit visit: CLVisit!)
{
    println("visit: \(visit.coordinate.latitude),\(visit.coordinate.longitude)")
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


}
like image 377
Lucas Farah Avatar asked Dec 15 '22 21:12

Lucas Farah


2 Answers

Your code looks correct. I've also found that CLVisit is not working the way I understood it should. It's tricky to debug, because you have to actually leave your workspace to test it. :)

The heuristics CLVisit uses to determine a "visit" are undocumented, but according to the WWDC video, you have to stay some unspecified amount of time before CLVisit decides you are visiting and not just passing by. I have had very limited success getting the delegate callback. Once the arrivalDate visit fired after about two minutes at a location, another after about ten minutes, but most times no visit ever fires.

NSLog doesn't work to catch CLVisits if you are out and about, so I set up a simple Core Data entity and I log all visits:

    Visits *thisVisit = [NSEntityDescription insertNewObjectForEntityForName:@"Visits" inManagedObjectContext:[self managedObjectContext]];
    thisVisit.arrivalDate = visit.arrivalDate;
    thisVisit.departureDate = visit.departureDate;
    thisVisit.latitude = [NSNumber numberWithDouble:visit.coordinate.latitude];
    thisVisit.longitude = [NSNumber numberWithDouble:visit.coordinate.longitude];
    [self saveContext];

Even when my device has been in my home location for many hours, I don't consistently get either an arrival or a departure event when I leave or return.

EDIT: Here's a complete sample. Install and use it for a few days and you'll see the issues with this new API. I hope it works better in later betas. It's still pretty inconsistent for me - two arrivals in a row sometimes, two departures in a row sometimes, long delays before visit fires...

https://github.com/steveschauer/TestCLVisit

like image 101
steve_sch Avatar answered Jan 04 '23 20:01

steve_sch


I assume that you're trying to get these delegate calls while the application is in the background; however, you're instantiating CLLocationManager in the view controller which won't be instantiated (afaik).

This works for me (I am using iOS 8, beta 2, on an iPad mini 2nd gen): Set the NSLocationAlwaysUsageDescription key, enable the "Location updates" background mode in Capabilities, and include the following in AppDelegate:

let locationManager = CLLocationManager()

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
    locationManager.delegate = self
    locationManager.requestAlwaysAuthorization()
    locationManager.startMonitoringVisits()

    return true
}

func locationManager(manager: CLLocationManager!, didVisit visit: CLVisit!) {
    println("Visit: \(visit)")
    // I find that sending this to a UILocalNotification is handy for debugging
}

Update: I have pushed an example application which works to https://github.com/mloughran/CLVisit-POC.

like image 43
mloughran Avatar answered Jan 04 '23 18:01

mloughran