IOS13:CoreLocation:CLVisit 稍后停止调用委托

IOS 13: CoreLocation: CLVisit stop calling delegate after a while

将我的 iPhone 升级到 IOS 13.* DidVisit CoreLocation 委托 的回调是不再可靠了。

我没有更改这方面的任何代码。自 IOS 9(应用程序开发开始)以来一切正常。

它像往常一样启动,但过了一会儿它停止调用回调 "didVisit" 然后没有任何东西让它恢复生机(有时重新启动正在恢复,有时是新的应用程序版本),但我没有看到任何模式...

有人看到同样的问题吗?

编辑:

正如 Nevan King 告诉我的那样,它甚至可以与 IOS 13 一起工作,我现在将提供相关的代码块和今天早上 运行 的日志。也许有人可以告诉我代码有什么问题...

位置管理器正在工作,委托回调(didUpdateLocations、didEnterRegion 等)都被调用,除了回调 "didVisit"。

真是奇怪!

首先:这是设置位置管理器的方法

// --------------------------------------------------------------------
// startRunLoop()
// --------------------------------------------------------------------
func startRunLoop(preferMain: Bool) {

    // before we start the location manager we wait for the user accepted the privacy explanation
    checkAndWaitForStartViewController(from: "WTSRunLoop startRunLoop(preferMain: \(preferMain)")

    // explicit call on main thread
    DispatchQueue.main.async(execute: {

        #if DEBUG_NSLOG_CUR
        NSLog("WTSRunLoop: set WTS_LocationManager, his delegate, WTS_MotionActivityManager and WTS_MotionActivityQueue")
        #endif

        // ---------------------------------------
        // first step, just cean up left overs, just to be on the save side
        if self.WTS_LocationManager != nil {
            if self.WTS_LocationManager!.delegate != nil {
                self.WTS_LocationManager!.delegate = nil
                #if DEBUG_NSLOG_CUR
                NSLog("WTSRunLoop: just set WTS_LocationManager!.delegate = nil, as it was not nil")
                #endif
            }
            self.WTS_LocationManager = nil
            #if DEBUG_NSLOG_CUR
            NSLog("WTSRunLoop: just set WTS_LocationManager = nil, as it was not nil")
            #endif
        }

        // get the location manager and set the delegate
        self.WTS_LocationManager = CLLocationManager()
        self.WTS_LocationManager!.delegate = self


        // set the semaphore, that we did create the location manager
        #if DEBUG_NSLOG_CUR
        NSLog("WTSRunLoop: call WTS_LocationManagerDispatchGroup.leave()")
        #endif
        WTS_LocationManagerDispatchGroup.leave()

        ...

     })
}

二:开启访问监控的方法

/**
 -----------------------------------------------------------------------------------------------

 WTS_StartVisitMonitoring()

 -----------------------------------------------------------------------------------------------
 */
var WTS_StartVisitMonitoringDone : Bool = false
func WTS_StartVisitMonitoring(checkRegion: Bool) {

    #if DEBUG_NSLOG_CUR
    NSLog("WTS_StartVisitMonitoring(): just started")
    #endif

    // just a test if we still run on the same locationManager
    if self.WTS_LocationManager != nil {

        if self.WTS_OldLocationManager != self.WTS_LocationManager {

            #if DEBUG_NSLOG_CUR
            NSLog("WTS_StartVisitMonitoring(): WTS_OldLocationManager (\(self.WTS_OldLocationManager.debugDescription)) != WTS_LocationManager (\(self.WTS_LocationManager.debugDescription)), set WTS_StartVisitMonitoringDone = false")
            #endif
            WTS_StartVisitMonitoringDone = false
            self.WTS_OldLocationManager = self.WTS_LocationManager
        }
    }

    // make sure we do this only once
    if self.WTS_StartVisitMonitoringDone == false {

        // set the flag
        self.WTS_StartVisitMonitoringDone = true

        // if we didn't have a valif location manager so far, wait for it
        if self.WTS_LocationManager == nil {

            #if DEBUG_NSLOG_CUR
            NSLog("WTS_StartVisitMonitoring(): WTS_LocationManager == nil, call WTS_LocationManagerDispatchGroup.wait()")
            #endif

            WTS_LocationManagerDispatchGroup.wait()
        }

        #if DEBUG_NSLOG_CUR
        NSLog("WTS_StartVisitMonitoring(): will try to call WTS_LocationManager!.startMonitoringVisits() on main thread")
        #endif

        DispatchQueue.main.async(execute: {
            #if DEBUG_NSLOG_CUR
            NSLog("WTS_StartVisitMonitoring().main: call WTS_LocationManager!.startMonitoringVisits() on main thread")
            #endif

            self.WTS_LocationManager!.startMonitoringVisits()
        })

        // check if we should do a check to adjust the visits Region
        if checkRegion == true {

            #if DEBUG_NSLOG_CUR
            NSLog("WTS_StartVisitMonitoring(): checkRegion == true, will call WTS_CheckForVisitRegion()")
            #endif
            self.WTS_CheckForVisitRegion()
        }

    } else {

        #if DEBUG_NSLOG_CUR
        NSLog("WTS_StartVisitMonitoring(): WTS_StartVisitMonitoringDone == \(self.WTS_StartVisitMonitoringDone), do nothing")
        #endif
    }
}

三:运行今早的日志相关部分

2019-11-08 06:10:13.647 App[2156:734589] WTSRunLoop init(), <<< IOS 13 >>> now call startRunLoop(true)
2019-11-08 06:10:13.647 App[2156:734589] checkAndWaitForStartViewController(from: WTSRunLoop startRunLoop(preferMain: true): just started, will call now myStartupDispatchGroup.wait()

...

2019-11-08 06:10:13.726 App[2156:734589] checkAndWaitForStartViewController(from: WTSRunLoop startRunLoop(preferMain: true): after myStartupDispatchGroup.wait(), return
2019-11-08 06:10:13.727 App[2156:734584] WTSRunLoop: set WTS_LocationManager, his delegate, WTS_MotionActivityManager and WTS_MotionActivityQueue
2019-11-08 06:10:13.728 App[2156:734589] WTS_StartTrackSystem(): just started, wait for StartViewController
2019-11-08 06:10:13.728 App[2156:734584] WTSRunLoop: call WTS_LocationManagerDispatchGroup.leave()
2019-11-08 06:10:13.728 App[2156:734584] WTSRunLoop: WTS_MotionActivityManager != nil, all OK
2019-11-08 06:10:13.728 App[2156:734584] WTSRunLoop: WTS_MotionActivityQueue != nil, all OK

...

2019-11-08 06:10:14.435 App[2156:734584] locationManager(didChangeAuthorization:): just started, call checkAndHandleAuthorizationStatus()
2019-11-08 06:10:14.436 App[2156:734584] checkAndHandleAuthorisationStatus(): User gave permission to use Localisation also when not in use, now we can work
2019-11-08 06:10:14.436 App[2156:734584] checkAndHandleAuthorisationStatus(): user decided about authorization, call myAuthorizationDispatchGroup.leave()
2019-11-08 06:10:14.436 App[2156:734584] locationManager(didChangeAuthorization:): new authorizationStatus = .authorizedAlways

....

2019-11-08 06:10:14.438 App[2156:734589] WTS_SetYellowRed(): will call WTS_StartVisitMonitoring()
2019-11-08 06:10:14.438 App[2156:734589] WTS_StartVisitMonitoring(): just started
2019-11-08 06:10:14.439 App[2156:734589] WTS_StartVisitMonitoring(): WTS_OldLocationManager (nil) != WTS_LocationManager (Optional(<CLLocationManager: 0x2816b5120>)), set WTS_StartVisitMonitoringDone = false
2019-11-08 06:10:14.439 App[2156:734589] WTS_StartVisitMonitoring(): will try to call WTS_LocationManager!.startMonitoringVisits() on myRunLoop
2019-11-08 06:10:14.439 App[2156:734589] WTS_StartVisitMonitoring(): checkRegion == true, will call WTS_CheckForVisitRegion()
...

2019-11-08 06:10:14.497 App[2156:734584] WTS_StartVisitMonitoring().main: call WTS_LocationManager!.startMonitoringVisits() on main thread

...

编辑 2:

信不信由你,在我重新启动 iPhone 后,应用程序收到了几个 didVisit 事件(见下文)...

但这都是昨天早上和之前发生的事情。昨天和晚上什么都没有...

有人对这种行为有解释吗?

2019-11-08 08:16:55.700 App[283:5235] didVisit: New VisitEvent: <Lat, Lon>, Arrival: 06.11.2019, 20:21:41, Depart: 01.01.4001, 01:00:00), accuracy: 40.45339263770871
2019-11-08 08:17:00.568 App[283:5235] didVisit: New VisitEvent: <Lat, Lon>, Arrival: 06.11.2019, 20:21:41, Depart: 07.11.2019, 00:47:57), accuracy: 24.207239944549148
2019-11-08 08:17:00.663 App[283:5235] didVisit: New VisitEvent: <Lat, Lon>, Arrival: 07.11.2019, 00:54:20, Depart: 01.01.4001, 01:00:00), accuracy: 85.76831155108509
2019-11-08 08:17:03.698 App[283:5235] didVisit: New VisitEvent: <Lat, Lon>, Arrival: 07.11.2019, 00:54:20, Depart: 07.11.2019, 07:08:39), accuracy: 64.95511399529799
2019-11-08 08:17:03.778 App[283:5235] didVisit: New VisitEvent: <Lat, Lon>, Arrival: 07.11.2019, 07:16:14, Depart: 01.01.4001, 01:00:00), accuracy: 46.553598849932335
2019-11-08 08:17:12.808 App[283:5235] didVisit: New VisitEvent: <Lat, Lon>, Arrival: 07.11.2019, 07:16:14, Depart: 07.11.2019, 07:42:07), accuracy: 105.4615461367936
2019-11-08 08:17:12.909 App[283:5235] didVisit: New VisitEvent: <Lat, Lon>, Arrival: 07.11.2019, 07:50:36, Depart: 01.01.4001, 01:00:00), accuracy: 58.591188713846954

编辑 3:

又发生了...出乎意料的是,"didVisit" 回调不再被调用...

我启动了应用程序并监控了设备日志。我在日志中找到了这个,对我来说看起来不错,还是我错过了什么?

定位守护进程确认开始访问记录

com.apple.locationd.Core    {"msg":"CLLocationManager", "event":"activity", "_cmd":"startMonitoringVisits", "self":"0x282655120"}

后来在状态消息中我发现:

locationd   com.apple.locationd.Core    {"msg":"Incoming message", "event":"activity", "name":"kCLConnectionMessageSignificantLocationVisit", "this":"0x10a0476d0", "registrationReceived":1}
locationd   com.apple.locationd.Core    {"msg":"#slv Client subscribe", "client":"myApp", "subscribe":1}

后来我发现了这个(好像访问记录开始了"VisitTimeStarted = ...")

locationd   com.apple.locationd.Core    {"msg":"#usesync Enqueued usage update message", "client":"myApp", "usage":"{\n    BackgroundLocationTimeStarted = \"595586042.0572129\";\n    FenceTimeStarted = \"595458288.958685\";\n    LocationTimeStarted = \"595586039.822194\";\n    NonPersistentSignificantTimeStopped = \"586698620.031068\";\n    ReceivingLocationInformationTimeStarted = \"595586039.836334\";\n    SignificantTimeStopped = \"594494158.865963\";\n    VisitTimeStarted = \"595458288.95714\";\n}"}

CLVisit 仍在工作,委托方法仍在 iOS 13 中被调用。后台位置的权限系统在 iOS 13 中发生了变化,因此后台位置 API 将只几天后开始工作,并且只有在用户授予后台权限的情况下。

如果您想立即进行访问,请尝试转到您的应用设置,将位置权限切换为 "Always"。它可能在 "When In Use"。有关更多信息,请观看 WWDC 2019 What's New in Core Location