簡體   English   中英

CLLocationManager區域監視委托類問題

[英]CLLocationManager region monitoring delegate class issue

我圍繞CoreLocation實現了一個自定義類,以進行iBeacon區域監視。

此類具有一些自定義屬性,我將使用這些屬性來存儲與信標有關的某些信息,以供以后使用(在進入和退出事件期間)。

我面臨的問題是當應用終止或在后台保留時,這些存儲的屬性不再可用。 我的意思是,假設該應用在后台/終止時找到了一個信標區域,通常情況下,該應用將在后台啟動供我們處理。 我想在此期間將存儲的屬性用於自定義操作。

有人遇到過這個問題嗎? 我做錯了嗎? 另外,我正在從當前正在使用的cocoapod庫中使用此類。

下面是我寫的課程。

 @available(iOS 9.0, *)
class BeaconManager: NSObject, CLLocationManagerDelegate {
   //these properties are becoming nil
   private var manager: CLLocationManager
   private var lastDetection: NSDate?
   private var isMonitoring = false
   private var repository: [String: DBeacon]
   private var monitoredRegions: [String: DBeacon] becoming nil
   private var notifyBackground = true

   static let sharedManager = BeaconManager()
   weak var delegate:BeaconProtocol?

   private override init() {
    manager = CLLocationManager()
    repository =  [:]
    monitoredRegions = [:]

    if CLLocationManager.authorizationStatus() != .AuthorizedAlways {
        manager.requestAlwaysAuthorization()
    }

    super.init()
    manager.delegate = self
}

func startMonitoringForBeacon(beacon: Beacon) throws {
    guard CLLocationManager.locationServicesEnabled() else {
        CFLogger.ERROR("Location services not enabled")
        throw BeaconErrorDomain.AuthorizationError(msg: "Location services not enabled")
    }

    guard CLLocationManager.authorizationStatus() == .AuthorizedAlways else {
        switch CLLocationManager.authorizationStatus() {
        case .Denied:
            throw BeaconErrorDomain.AuthorizationError(msg: "User denied location services")
        case .Restricted:
            throw BeaconErrorDomain.AuthorizationError(msg: "App is prevented from accessing Location Services")
        default:
            throw BeaconErrorDomain.AuthorizationError(msg: "App doesn't have authorization to monitor regions")
        }
    }

    guard CLLocationManager.isMonitoringAvailableForClass(CLBeaconRegion) else {
        CFLogger.ERROR("Region monitoring not available on this device")
        throw DBeaconKitErrorDomain.RegionMonitoringError(msg: "Region monitoring not available on this device")
    }


    guard let auuid = NSUUID(UUIDString: beacon.uuid) else {
        throw BeaconErrorDomain.InvalidUUIDString
    }

    let region:CLBeaconRegion!

    switch (beacon.major, beacon.minor) {
        case (.None, .None):
            region = CLBeaconRegion(proximityUUID: auuid, identifier: dbeacon.identifier)
        case (.Some(let major), .None):
            region = CLBeaconRegion(proximityUUID: auuid, major: UInt16(major), identifier: beacon.identifier)
        case (.Some(let major), .Some(let minor)):
            region = CLBeaconRegion(proximityUUID: auuid, major: UInt16(major), minor: UInt16(minor), identifier: beacon.identifier)
        default:
            throw BeaconErrorDomain.InvalidDBeaconInfo
    }

    region.notifyEntryStateOnDisplay = false
    region.notifyOnEntry = true
    region.notifyOnExit = true

    repository[beacon.identifier] = beacon
    manager.startMonitoringForRegion(region)
}

func stopMonitoringForBeacons(beacons: [Beacon]) {
    guard isMonitoring else {
        return
    }

    beacons.forEach { (dbeacon) -> () in
        stopMonitoringForBeacon(beacon)
    }
}

func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
    guard let handler = delegate else {
        return
    }

    handler.initializationFailed(error)
}

func locationManager(manager: CLLocationManager, didStartMonitoringForRegion region: CLRegion) {
    guard let aregion = region as? CLBeaconRegion, beacon = repository[aregion.identifier] else {
        return
    }

    isMonitoring = true

    monitoredRegions[aregion.identifier] = beacon
    manager.requestStateForRegion(region)
}

func locationManager(manager: CLLocationManager, monitoringDidFailForRegion region: CLRegion?, withError error: NSError) {
    guard let aregion = region as? CLBeaconRegion, beacon = repository[aregion.identifier], handler = delegate else {
        return
    }

    handler.monitoringFailedForRegion(beacon, error: error)
}

func locationManager(manager: CLLocationManager, didEnterRegion region: CLRegion) {
    guard let aregion = region as? CLBeaconRegion else {
        return
    }

    guard let beacon = monitoredRegions[aregion.identifier] else {
        return
    }

    guard let handler = delegate else {
     print("Handler not available to report beacon entry event \(region.identifier)")
        return
    }

    print("Entered beacon region \(beacon)")
    handler.entered(beacon)
}

func locationManager(manager: CLLocationManager, didExitRegion region: CLRegion) {
    guard let aregion = region as? CLBeaconRegion, beacon = monitoredRegions[aregion.identifier], handler = delegate else {
        print("Handler not available to report beacon exit event \(region.identifier)")
        return
    }

    print("Exited beacon region \(beacon)")
    handler.exited(beacon)
}
 }

我最終發現存儲的屬性沒有啟動區域監視時設置的值。

任何幫助,我們都感激不盡。

問候。

如@ Paulw11所說,這些屬性在應用程序重新啟動時會丟失其初始化值。 解決此問題的典型方法是將這些屬性存儲到NSUserDefaults 下面的代碼片段顯示了如何還原init方法底部的lastDetection字段。 一旦更改,則必須調用第二個方法save()來保留該字段。

private override init() {
    manager = CLLocationManager()
    repository =  [:]
    monitoredRegions = [:]

    if CLLocationManager.authorizationStatus() != .AuthorizedAlways {
        manager.requestAlwaysAuthorization()
    }

    super.init()
    manager.delegate = self

    let userDefaults = NSUserDefaults.standardUserDefaults()    
    lastDetection = userDefaults.valueForKey("last_detection") as! NSDate?

}

func save() {
    let userDefaults = NSUserDefaults.standardUserDefaults()    
    userDefaults.setValue(lastDetection, forKey: "last_detection")
}

上面的示例僅顯示了保存和還原單個屬性。 你需要與他們做到這一點,有的會更復雜的處理(如monitoredRegionsrepository ),因為它們是不能直接被序列化到復雜的數據類型NSUserDefaults 要進行此序列化,您可以嘗試使用JSON將它們轉換為可以存儲的字符串,然后從同一字符串中解析出它們。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM