我正在尝试设置客户端应用,以便在iOS设备到达/离开办公室时触发数据库更新。
(它是我的客户和销售人员在现场使用的应用程序,其中一些客户站点没有任何网络连接,因此客户希望在销售人员离开办公室时更新数据库/回到办公室。)
我永远不会收到didEnterRegion
或didExitRegion
来电。
我有一个单身RegionsManager
来管理位置管理器的实例。
我使用CLLocationManager
和startMonitoringForRegion
方法。
启动时,我调用RegionsManager
创建一个位置管理器,并将自己设置为位置管理员的代表。
在我的应用代表的didFinishLaunchingWithOptions
方法中,我检查UIApplicationLaunchOptionsLocationKey
,以防我重新启动输入/退出的区域,但这种情况从未发生过。
我在info.plist中有一个NSLocationAlwaysUsageDescription
键/值对。
我致电CLLocationManager.authorizationStatus
以确保该应用已获得授权,如果没有,请致电requestAlwaysAuthorization
。
一旦我确认该应用已获得授权,我还会检查isMonitoringAvailableForClass(CLCircularRegion)。
假设监控可用,我然后检查位置管理器的monitoredRegions
集是否已经包含我要创建的区域(我只是检查坐标)。如果是这样,我会跳过添加区域。
如果位置管理员尚未监控该区域,我会通过调用startMonitoringForRegion
来添加它。
在应用程序的第二次启动时,我看到我在上次启动时在位置管理器的monitoredRegions
集中添加的区域,因此我知道它们已被添加。
设置所有这些的代码非常复杂,因为它设置为处理添加多个区域,并且还具有维护被监视区域数组的逻辑以及如果on { {1}}或didEnterRegion
消息。
以下是有问题的方法(相当长)整个:
didExitRegion
我的RegionsManager类有func startMonitoring(#coordinate: CLLocationCoordinate2D,
radius: CLLocationDistance = regionDistance,
id: String = "",
notificationBlock: regionNotificationBlock)
{
var authorizationStatus = CLLocationManager.authorizationStatus()
if !locationManagerReady
{
//Make sure we're authorized to use the location manager.
if authorizationStatus == .NotDetermined && !waitingForAuthorization
{
//We haven't been authorized yet. Trigger a prompt to the user.
theLocationMgr.requestAlwaysAuthorization()
waitingForAuthorization = true
authorizationStatus = CLLocationManager.authorizationStatus()
}
//Wait for the user to grant/deny permission.
if authorizationStatus == .NotDetermined
{
//After 1 second, re-call this method to try again.
delay(1.0)
{
()-> () in
self.startMonitoring(
coordinate: coordinate,
radius: radius,
id: id,
notificationBlock: notificationBlock)
}
return
}
let rootVC: UIViewController? = UIApplication.sharedApplication().keyWindow?.rootViewController
if authorizationStatus == CLAuthorizationStatus.Restricted ||
authorizationStatus == CLAuthorizationStatus.Denied
{
Utils.showAlertOnVC(
rootVC,
title: "Location manager error",
message: "Permission to access location denied")
return
}
else if !CLLocationManager.isMonitoringAvailableForClass(CLCircularRegion)
{
Utils.showAlertOnVC(
rootVC,
title: "Location manager error",
message: "geofencing is not available.")
return
}
}
if !locationManagerReady
{
locationManagerReady = true
theLocationMgr.desiredAccuracy = kCLLocationAccuracyBest
theLocationMgr.distanceFilter = kCLDistanceFilterNone;
}
//If we get here, we're done configuring the location manager
//If this region is already in our array of regions, don't add it again.
if let existingRegionIndex = regionIndexForCoordinate(coordinate)
{
return
}
let regionToMonitor = CLCircularRegion(
center: coordinate,
radius: radius,
identifier: id)
//See if the system is still monitoring this region from a previous launch.
var found = false
var foundRegion: CLCircularRegion? = nil
if let monitoredRegions = theLocationMgr.monitoredRegions as NSSet?
{
let regionsArray = monitoredRegions.allObjects as NSArray
let regionIndex = regionsArray.indexOfObjectPassingTest()
{ (object, index, flag) -> Bool in
if let region = object as? CLCircularRegion
{
return region.center.latitude == coordinate.latitude &&
region.center.longitude == coordinate.longitude
}
else
{
return false
}
}
found = regionIndex != NSNotFound
if found
{
foundRegion = regionsArray[regionIndex] as? CLCircularRegion
}
}
if found
{
logToFile("already monitoring (\(coordinate.latitude),\(coordinate.longitude)). ID = '\(foundRegion!.identifier!)'")
}
else
{
logToFile("Adding geofence for (\(coordinate.latitude),\(coordinate.longitude)). ID = '\(id)'")
theLocationMgr.startMonitoringForRegion(regionToMonitor)
}
let aRegionEntry = RegionEntry(region: regionToMonitor, regionNoticeBlock: notificationBlock)
regionsBeingMonitored.append(aRegionEntry)
}
个regionsBeingMonitored
个对象的数组:
RegionEntry
这是RegionEntry对象:
lazy var regionsBeingMonitored = [RegionEntry]()
它还有状态标志来跟踪位置管理器的设置:
class RegionEntry: NSObject
{
var theRegion: CLCircularRegion?
var theRegionNoticeBlock: regionNotificationBlock?
init(region: CLCircularRegion?, regionNoticeBlock: regionNotificationBlock?)
{
theRegion = region
theRegionNoticeBlock = regionNoticeBlock
}
}
我已经仔细阅读了关于设置区域监控的文档,我非常有信心我正在做我应该做的所有设置。
我的didEnterRegion和didExitRegion方法在调用它们后立即将消息写入日志文件,因此,即使我的逻辑存在问题,我的逻辑仍然存在我的var waitingForAuthorization: Bool = false
var locationManagerReady: Bool = false
数组中的条目匹配区域请参阅日志条目:
regionsBeingMonitored
你看到我可能做错了吗?我func locationManager(manager: CLLocationManager!,
didEnterRegion region: CLRegion!)
{
logToFile("In \(__FUNCTION__). region = \(region)")
if let region = region as? CLCircularRegion
{
if let regionIndex = regionIndexForCoordinate(region.center)
{
let aRegionEntry = regionsBeingMonitored[regionIndex]
aRegionEntry.theRegionNoticeBlock?(region: region, didEnter: true)
}
}
}
func locationManager(manager: CLLocationManager!,
didExitRegion region: CLRegion!)
{
logToFile("In \(__FUNCTION__). region = \(region)")
if let region = region as? CLCircularRegion
{
if let regionIndex = regionIndexForCoordinate(region.center)
{
let aRegionEntry = regionsBeingMonitored[regionIndex]
aRegionEntry.theRegionNoticeBlock?(region: region, didEnter: false)
}
}
}
或didEnterRegion
的方法签名看起来是正确的,所以我不认为这是正确的。