如果不在ViewController中,则不会调用Estimote didChangeAuthorizationStatus

时间:2015-12-11 13:09:18

标签: ios objective-c swift localization estimote

我想在方法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

Separedted BeaconManager

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(已经尝试过)。

1 个答案:

答案 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 )保持不变。