簡體   English   中英

了解iOS中的iBeacon:didDetermineState和didEnterRegion事件

[英]Understanding iBeacons in iOS: didDetermineState and didEnterRegion events

第一部分:

我編寫了以下代碼來監視iBeacon。 我想檢測didEnterRegiondidExitRegion事件。 但是它永遠不會發生。 您能否看一下代碼並提出可能遺漏的內容?

我使用Apple AirLocate示例代碼將一台設備配置為iBeacon,並執行以下步驟來測試我的代碼:

腳步:

  1. 在設備B上編譯並執行AirLocate示例代碼
  2. 在設備A上編譯並執行此代碼
  3. 在設備B中,使用AirLocate應用將設備配置為iBeacon,選擇以下UUID:“ 74278BDA-B644-4520-8F0C-720EAF059935”

結果:

  • 郵件內的狀態

預期成績:

  • 郵件內的狀態
  • 確實進入了區域

這是為什么?

這些是我的plist條目:

在此處輸入圖片說明

碼:

#import "BeaconMonitoring.h"

@implementation BeaconMonitoring

- (instancetype)init
{
    self = [super init];
    if (self) {
        self.locationManager = [[CLLocationManager alloc] init];

        if([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
            [self.locationManager requestAlwaysAuthorization];
        }

        self.locationManager.delegate = self;
        self.locationManager.pausesLocationUpdatesAutomatically = NO;

        self.monitoredRegions = [[NSMutableArray alloc] initWithCapacity:10];
    }
    return self;
}

- (void) startRangingForBeacons{
    NSLog(@"in startRangingForBeacons");
    [self.locationManager startUpdatingLocation];
    [self startMonitoringForRegion:[[NSUUID alloc] initWithUUIDString:@"74278BDA-B644-4520-8F0C-720EAF059935"] :@"b"];
}

- (void) startMonitoringForRegion:(NSUUID*)beaconUUID :(NSString*)regionIdentifier{
   /**
    Alternatively:
    CLBeaconRegion *beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:@"xxxx"
    major:10
    minor:20
    identifier:@"name"]
    **/

    // Override point for customization after application launch.
    CLBeaconRegion *beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:beaconUUID identifier:regionIdentifier];

    beaconRegion.notifyEntryStateOnDisplay = NO;
    beaconRegion.notifyOnEntry = YES;
    beaconRegion.notifyOnExit  = YES;

    [self.locationManager startMonitoringForRegion:beaconRegion];
    [self.locationManager startRangingBeaconsInRegion:beaconRegion];
    [self.monitoredRegions addObject:beaconRegion];
}

- (void) stopRangingForbeacons{
    NSLog(@"in stopRangingForbeacons");
    [self.locationManager stopUpdatingLocation];

    for (int i=0; i < [self.monitoredRegions count]; i++) {
        NSObject * object = [self.monitoredRegions objectAtIndex:i];

        if ([object isKindOfClass:[CLBeaconRegion class]]) {
            CLBeaconRegion * region = (CLBeaconRegion*)object;
            [self.locationManager stopMonitoringForRegion:region];
            [self.locationManager stopRangingBeaconsInRegion:region];
        }
        else{
            NSLog(@"Serious error, should never happen!");
        }
    }
}


#pragma CLLocationManagerDelegate

-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region {
    [manager startRangingBeaconsInRegion:(CLBeaconRegion*)region];
    [self.locationManager startUpdatingLocation];
    NSLog(@"You entered the region.");
}

-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region {
    [manager stopRangingBeaconsInRegion:(CLBeaconRegion*)region];
    [self.locationManager stopUpdatingLocation];


    NSDictionary * notificationData = @{ @"value" : @"exitedRegion"};
    [[NSNotificationCenter defaultCenter] postNotificationName:@"dataUpdate" object:nil userInfo:notificationData];

    NSLog(@"You exited the region.");
    // [self sendLocalNotificationWithMessage:@"You exited the region."];
}

- (void) locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region
{
    NSLog(@"did determine state");

    switch (state) {
        case CLRegionStateInside:
            NSLog(@"state inside");
            break;
        case CLRegionStateOutside:
            NSLog(@"state outside");
            break;
        case CLRegionStateUnknown:
            NSLog(@"state unknown");
            break;
        default:
            NSLog(@"Default case: Region unknown");
            break;
    }
}

-(void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region {

    NSLog(@"Did range %lu beacon in region %@", (unsigned long)[beacons count], region.identifier);

    NSString * visibleInformation = [NSString stringWithFormat:@"(%lu)", (unsigned long)[beacons count]];

    for (int i=0; i<[beacons count]; i++) {
        CLBeacon *beacon = [beacons objectAtIndex:i];

        if ([beacons count] == 1) {
            NSNumber * distance =  [NSNumber numberWithFloat:beacon.accuracy];
            visibleInformation = [NSString stringWithFormat:@"%i-%i is %f", beacon.major.intValue, beacon.minor.intValue, distance.doubleValue];
        }
        else{
            visibleInformation = [visibleInformation stringByAppendingString:[NSString stringWithFormat:@" %i-%i ", beacon.major.intValue, beacon.minor.intValue]];
        }
    }
}

@end

第二部分:

我查看了AirLocate源代碼,以了解是否必須在消息內部的狀態中觸發某些內容才能使監視正常工作。 但是我發現** didDetermineState **方法是在AppDelegate中實現的。

這是為什么?

- (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region
{
    /*
     A user can transition in or out of a region while the application is not running. When this happens CoreLocation will launch the application momentarily, call this delegate method and we will let the user know via a local notification.
     */
    UILocalNotification *notification = [[UILocalNotification alloc] init];

    if(state == CLRegionStateInside)
    {
        notification.alertBody = NSLocalizedString(@"You're inside the region", @"");
    }
    else if(state == CLRegionStateOutside)
    {
        notification.alertBody = NSLocalizedString(@"You're outside the region", @"");
    }
    else
    {
        return;
    }

    /*
     If the application is in the foreground, it will get a callback to application:didReceiveLocalNotification:.
     If it's not, iOS will display the notification to the user.
     */
    [[UIApplication sharedApplication] presentLocalNotificationNow:notification];
}

假設:R =由B構成並由A收聽的區域

情況1

如果A在B之前開始:

  1. 應用A應該告訴您確定區域R =外部的狀態
  2. 應用A應該運行didEnter進入區域R

情況2

如果A實際上是在B之后開始的:

  1. 它應該只運行defineState Region R = inside

結束。 這里沒有2,因為它永遠不會進入范圍。 它開始於里面

暫無
暫無

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

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