2016-03-02 68 views
0

我正在構建可與iBeacons配合使用的應用程序。我正在監視特定的信標,並想知道我的手機何時進入和退出某個區域。進入適當的工作,我知道退出與他們有30秒的超時。但是,我遇到了我只能描述爲發生退出時的超時重置。下面是一個例子:didExitRegion計時器在同時退出期間重置

  • 退出信標1
  • 15秒後退出信標2
  • didExitRegion發生用於信標1 15秒後。
  • didExitRegion發生信標2 30秒後(它應該只需要15秒以上)

第二個例子:

  • 退出信標1和信標2同時進行。
  • didExitRegion出現在信標1 30秒後
  • didExitRegion發生在信標2之後30秒。

我知道這些信標應該退出,因爲我使用硬件版本3.2的estimote信標,它可以翻轉到休眠模式,所以信標在倒置時停止廣播。因此,就像第二個例子一樣,即使我正在單獨監視每個燈標,在註冊出口之前,信標也可能在整整一分鐘內未被檢測到。有誰知道是否有解決辦法,或者這只是iOS信標監測中的一個錯誤?

有趣的是,如果你同時退出兩個以上的信標,其中一個會在30之後退出,其餘的會在30秒後退出,因此Apple能夠檢測到這些不同的信號正在單獨退出無論UUID,主要和次要的組合

。這是我的程序的基本功能:

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view, typically from a nib. 
    CLBeaconRegion *region = [[CLBeaconRegion alloc] initWithProximityUUID:[[NSUUID alloc] initWithUUIDString:@"B9407F30-F5F8-466E-AFF9-25556B57FE6D" ] identifier:@"beacon"]; 
    [self.locationManager startMonitoringForRegion:region]; 
    [self.locationManager requestStateForRegion:region]; 
    self.view.backgroundColor = [UIColor redColor]; 
} 

- (CLLocationManager *)locationManager { 
    if (!_locationManager) { 
     NSLog(@"location manager alloc init"); 
     _locationManager = [[CLLocationManager alloc] init]; 
     [_locationManager requestAlwaysAuthorization]; 
     _locationManager.delegate = self; 
    } 
    return _locationManager; 
} 

#pragma mark - CLLocationManagerDelegate 

-(void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region { 
    NSLog(@"didStartMonitoringRegion: %@", region); 
} 

- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region { 
    NSLog(@"didEnterRegion: %@", region); 
    if ([region isKindOfClass:[CLBeaconRegion class]]) { 
     CLBeaconRegion *beaconRegion = (CLBeaconRegion *)region; 
     if (beaconRegion.major && beaconRegion.minor) { 
      NSLog(@"entered specific!"); 
     } else { 
      NSLog(@"entered the general region!"); 
      NSLog(@"will start Ranging!"); 
      [self.locationManager startRangingBeaconsInRegion:beaconRegion]; 
     } 
    } 
} 

- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region { 
    NSLog(@"didExitRegion: %@", region); 
    if ([region isKindOfClass:[CLBeaconRegion class]]) { 
     CLBeaconRegion *beaconRegion = (CLBeaconRegion *)region; 
     if (beaconRegion.major && beaconRegion.minor) { 
      NSLog(@"stop monitoring %@ %@", beaconRegion.major, beaconRegion.minor); 
      [self.locationManager stopMonitoringForRegion:beaconRegion]; 
     } else { 
      NSLog(@"will stop ranging on %@", beaconRegion.proximityUUID.UUIDString); 
      [self.locationManager stopRangingBeaconsInRegion:beaconRegion]; 
     } 
    } 
} 

- (void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray<CLBeacon *> *)beacons inRegion:(CLBeaconRegion *)region { 
    for (CLBeacon *beacon in beacons) { 
     NSLog(@"ranging %@ %@", beacon.major, beacon.minor); 
     CLBeaconRegion *beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:beacon.proximityUUID major:beacon.major.shortValue minor:beacon.minor.shortValue identifier:[NSString stringWithFormat:@"%@ %@ %@", beacon.proximityUUID.UUIDString, beacon.major, beacon.minor]]; 
     if (![self.locationManager.monitoredRegions containsObject:beaconRegion]) { 
      [self.locationManager startMonitoringForRegion:beaconRegion]; 
     } 
    } 
} 

- (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region { 
    NSLog(@"didDetermineStateForRegion %@", region); 
} 

我監視特定的UUID,然後當我遇到UUID我開始爲就可以了。然後,我開始監視在該UUID中遇到的每個特定信標。當我不再與該UUID遇到任何信標時,我停止測距。這個bug對我來說很不好,因爲它實際上迫使我額外增加30秒,我想限制它以節約電池

+0

有趣。我沒有目睹過這種行爲。我很想知道它是否發生在其他類型的燈塔上。如果你可以發佈一個簡短版本的程序來證明這一點,那麼對其他人來說,嘗試重現將會很有用。 – davidgyoung

+0

我添加了一些代碼來澄清發生了什麼 – RDSpinz

+0

我不確定,但我懷疑它是當您退出可能導致此問題的區域時停止監視的行爲。你需要在退出時停止監控嗎? – davidgyoung

回答

0

如果目標是儘快停止測距以節省電池,則不需要依靠監控區域出口。相反,您可以簡單地爲每個檢測到的信標維護一個時間戳。如果過去檢測到該信標的時間戳超過了X秒,則可以停止測距。如果你願意,這可以讓你自定義它甚至不到30秒。

如果您選擇走此路線,您應該注意的一件事是,如果您獲得RSSI爲0的信標的範圍回調,則表明它在上一週期中未檢測到。因此,您只需要更新具有非零RSSI的回調的時間戳。

我知道這是一種解決問題的辦法,而不是直接解決您所問的問題,所以只有在找不到解決監控區域退出時間差異的更直接解決方案時才提供此解決方案。

+0

雅這將在前臺工作,但是當應用程序在測距後進入後臺睡眠時(我已經按照您的建議延長了3分鐘時間),手機需要在死燈時監視這些信標。那麼我只會在它發生後1分鐘通知第二個出口。因此背景時間將是不正確的。如果他們的應用程序睡眠了超過指定的退出時間,然後根據第一個出口喚醒,它會退出,然後立即重新進入第二個燈塔。 – RDSpinz