我想在方法startMonitoringForRegion
中调用didChangeAuthorizationStatus
,一切正常,主要是因为代码是从Estimote
示例复制的。此代码位于ViewController
。当我使用类似的代码但放在分离的控制器中时会出现问题。
此代码工作正常,方法didChangeAuthorizationStatus
每次都调用didStartMonitoringForRegion
,因此我打开app或changeStatus。如此成功。
的 ViewController.m
- (void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
self.region = [[CLBeaconRegion alloc] initWithProximityUUID:[[NSUUID alloc] initWithUUIDString:@"myUUID"]
identifier:@"EstimoteSampleRegion"];
self.beaconManager = [[ESTBeaconManager alloc] init];
self.beaconManager.delegate = self;
[self startRangingBeacons];
}
-(void)startRangingBeacons
{
if ([ESTBeaconManager authorizationStatus] == kCLAuthorizationStatusNotDetermined)
{
[self.beaconManager requestAlwaysAuthorization];
}
else if([ESTBeaconManager authorizationStatus] == kCLAuthorizationStatusDenied)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Location Access Denied"
message:@"You have denied access to location services. Change this in app settings."
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles: nil];
[alert show];
}
else if([ESTBeaconManager authorizationStatus] == kCLAuthorizationStatusRestricted)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Location Not Available"
message:@"You have no access to location services."
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles: nil];
[alert show];
}
}
- (void)beaconManager:(id)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
if (status != kCLAuthorizationStatusNotDetermined && status != kCLAuthorizationStatusDenied )
{
[self.beaconManager startMonitoringForRegion:self.region];
}
}
- (void)beaconManager:(id)manager didStartMonitoringForRegion:(CLBeaconRegion *)region{
NSLog(@"didStartMonitoringForRegion %@",region);
}
此代码部分有效。 requestAlwaysAuthorization
中的方法BeaconManager
正在调用一次,但是当我手动调用didChangeAuthorizationStatus
时,startMonitoringForRegion
甚至不会调用方法didStartMonitoringForRegion
。
ViewController.m
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
self.region = [[CLBeaconRegion alloc] initWithProximityUUID:[[NSUUID alloc] initWithUUIDString:@"myUUID"]
identifier:@"EstimoteSampleRegion"];
self.beaconManager = [[BeaconManager alloc]initWithRegion:self.region];
[self.beaconManager startMonitoring];
}
BeaconManager.swift
class BeaconManager: NSObject,ESTBeaconManagerDelegate {
private lazy var secureBeaconManager:ESTSecureBeaconManager = {
let beaconManagerForReturn = ESTSecureBeaconManager()
beaconManagerForReturn.delegate = self
return beaconManagerForReturn
}()
private lazy var beaconsArray = [CLBeacon]()
var region:CLBeaconRegion!
var delegate:BeaconDelegate?
init(region:CLBeaconRegion) {
super.init()
self.region = region
}
/**
Method which check AuthorizationStatus for application, and will start monitoring if status is equal .AuthorizedAlways
*/
func startMonitoring() {
setupLocalizationAuthorization()
}
private func setupLocalizationAuthorization(){
let status = ESTSecureBeaconManager.authorizationStatus()
if (status == .NotDetermined){
secureBeaconManager.requestAlwaysAuthorization()
}
if (status == .Denied){
delegate?.beaconManager(self, locationAutorizationFail: .Denied)
}
if (status == .Restricted){
delegate?.beaconManager(self, locationAutorizationFail: .Restricted)
}
}
// MARK: - BeaconManager
func beaconManager(manager: AnyObject, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
if (status != .NotDetermined && status != .Denied){
secureBeaconManager.startMonitoringForRegion(region)
}
}
func beaconManager(manager: AnyObject, didStartMonitoringForRegion region: CLBeaconRegion) {
print("didStartMonitoring for \(region)")
}
}
问题
为什么会这样?这是线程问题?我不知道这里出了什么问题。从我可以看到两个代码相似但指令放在不同的地方。无论如果我使用Swift或Obj-c(已经尝试过)。
答案 0 :(得分:1)
分析第一次启动应用时会发生什么:
您实例化BeaconManager
并致电startMonitoring
,然后拨打setupLocalizationAuthorization
。在那里,你检查你的应用程序的授权状态,如果它是 NotDetermined ,你实例化secureBeaconManager
(因为你宣称它是一个懒惰的属性),分配代表(通过你的懒惰实例)代码),并致电requestAlwaysAuthorization
。这会提示用户允许该应用访问位置服务,如果他们同意,iOS会使用新的始终状态向didChangeAuthorizationStatus
发出呼叫,您最终会开始监控。正如您所提到的,此流程按预期工作。
但请考虑应用已经拥有始终授权的流程:
您实例化BeaconManager
并致电startMonitoring
,然后拨打setupLocalizationAuthorization
。在那里,您可以检查应用的授权状态。但是对于始终状态,你没有if
条款......所以BeaconManager
只是在那里结束。
解决方案:为您的if
始终状态添加setupLocalizationAuthorization
条款:
if status == .AuthorizedAlways {
secureBeaconManager.startMonitoringForRegion(region)
}
让我们对实施建议的解决方案时发生的事情进行最后一次传递:
您实例化BeaconManager
并致电startMonitoring
,然后拨打setupLocalizationAuthorization
。在那里,您可以检查应用的授权状态。如果它是始终,则懒惰实例化secureBeaconManager
,并开始监控。上一个流程( NotDetermined )保持不变。