2012-09-10 41 views
7

如果應用程序正在運行,並且CLLocationManagerDelegate類是前景(即可見),則didEnterRegions觸發器,我同時得到NSLog和AlertView。然而,當應用程序處於後臺時,我什麼也得不到,或者實際上,如果屏幕顯示除委託類以外的任何內容。didEnterRegion在前臺工作,但不在後臺或其他VC

我已經在plist的「所需的背景模式」下設置了「位置更新的應用寄存器」,儘管我不確定這是甚至必要的。

這是我認爲是相關的代碼,雖然我可能是錯的(並會很樂意添加更多)。我應該注意,viewDidLoad中的所有內容都包含在一個if中,用於檢查區域監視是否可用並已啓用。

- (void)viewDidLoad 
{ 
    NSLog(@"MapViewController - viewDidLoad"); 
    self.locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters; 
    self.locationManager.distanceFilter = kCLLocationAccuracyNearestTenMeters;  
    self.locationManager.delegate = self; 
    [self.locationManager startMonitoringSignificantLocationChanges]; 
} 

- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region 
{ 
    NSLog(@"MapViewController - didEnterRegion"); 
    NSLog(@"MVC - didEnterRegion - region.radius = %f", region.radius); 
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"entered region..." message:@"You have Entered the Location." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; 
    alert.tag = 2; 
    [alert show]; 
} 

這裏是我得到被監控區域的名單,在AppDelegate.m:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 

// other code 

NSLog(@"LISTING ALL REGIONS MONITORED"); 
    NSArray *regions = [self.locationManager.monitoredRegions allObjects]; 
    if (!regions) { 
     NSLog(@"no regions found"); 
    } else { 
     NSLog(@"got %d monitored regions", [regions count]); 
     for (int i = 0; i < [regions count]; i++) { 
      CLRegion *region = [regions objectAtIndex:i]; 
      NSLog(@"region %d's identifier = %@", i, region.identifier); 
      NSLog(@"region: radius: %@", region.radius); 
     } 
    } 

// other code 
} 

我打電話startMonitoringForRegion兩次,這裏的主要場所:

- (void)doneButtonTapped { 
    NSLog(@"doneButtonTapped"); 

    if (self.locationIdentifier) { 
     if ([CLLocationManager regionMonitoringEnabled] && [CLLocationManager regionMonitoringAvailable]) { 

      // core data setup 
      NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
      NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"LocationReminder" inManagedObjectContext:self.managedObjectContext]; 
      fetchRequest.entity = entityDescription; 
      NSPredicate *predicate = [NSPredicate predicateWithFormat:@"locationIdentifier == %@", self.locationIdentifier]; 
      fetchRequest.predicate = predicate; 
      NSError *error; 
      NSArray *results = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error]; 
      if (results) { 

       // get the LocationReminder 
       LocationReminder *retrievedReminder = [results objectAtIndex:0]; 
       retrievedReminder.audioURI = [[[self.audioPlayers objectAtIndex:self.selectedCell] url] absoluteString]; 
       retrievedReminder.userRecording = nil; 

       // start monitoring it's region 
       NSArray *coordinateArray = [retrievedReminder.locationIdentifier componentsSeparatedByString:@", "]; 
       CLLocationCoordinate2D coordinate = {[[coordinateArray objectAtIndex:0] doubleValue], [[coordinateArray objectAtIndex:1] doubleValue]}; 
       CLRegion *newRegion = [[CLRegion alloc] initCircularRegionWithCenter:coordinate radius:250.0 identifier:retrievedReminder.locationIdentifier]; 
       NSLog(@"about to monitor region with radius: %f", newRegion.radius); 
       [self.locationManager startMonitoringForRegion:newRegion desiredAccuracy:kCLLocationAccuracyBest]; 

       // save the LocationReminder 
       if (![self.managedObjectContext save:&error]) { 
        NSLog(@"hmm. no managed object context. must be something space-time going on"); 
       } else { 
        NSLog(@"saved locationReminder, locationIdentifier = %@", retrievedReminder.locationIdentifier); 
       } 
      } else { 
       NSLog(@"ERROR: no LocationReminder retreived for predicate: %@", predicate); 
      } 
     } 

     // get the mapview controller off of the navigation stack 
     for (UIViewController *viewController in self.navigationController.viewControllers) { 
      if ([viewController isKindOfClass:[MapViewController class]]) { 
       MapViewController *mapVC = (MapViewController *)viewController; 
       mapVC.audioURI = [[[self.audioPlayers objectAtIndex:self.selectedCell] url] absoluteString]; 
       [self.navigationController popToViewController:mapVC animated:YES]; 
      } 
     } 
} 

而且由於我覺得這可能很重要,這裏是locationManager的獲取者:

- (CLLocationManager *)locationManager { 
    NSLog(@"MapViewController - locationManager"); 
    if (_locationManager) { 
     return _locationManager; 
    } else { 
     _locationManager = [[CLLocationManager alloc] init]; 
     return _locationManager; 
    } 
} 

更新1:通過蘋果論壇(我在那裏交叉)有人提到AlertView將只顯示在前臺。 NSLog也不會觸發。我假設應該工作。

+0

您可以包含您調用startMonitoringForRegion的代碼嗎?目前包含的代碼沒有顯示,只會觸發與重大位置更改相關的回調方法。根據我的經驗,這些事件不會從模擬器中觸發。 –

回答

3

我的一個朋友寫了一篇關於使用geofencing的好教程,可能有助於解決您遇到的一些問題。

Get started with geofencing

有很多在線的例子,在這裏對SO。從小處開始,繼續前進。一旦你開始得到你的回調,你可以開始擴展到其他視圖控制器。

UPDATE

正如評論解釋創建一個單獨的類來控制你的位置,經理和委託方法的好處。通過使用單例,可以避免多次調用委託方法的可能性。你可以通過仔細的編碼來防止這種情況,但是使用單例可以爲你做到這一點。這也是一個很好的類來處理委託方法需要完成的所有工作。

+2

感謝您的鏈接。我很確定我已經涵蓋了所有這些基礎。在這一點上,我認爲更多的是應用程序進入和退出的背景,而不是區域監控。實際上,它對我來說有相當大的意義,它只能在CLLocationManagerDelegate中工作 - didEnterRegion應該如何被調用? iOS有足夠的知識來喚醒應用程序並實例化正確的VC嗎?我想知道是否必須對UIApplicationDelegate協議做些什麼。 –

+1

另一方面,在位置感知編程指南中根本沒有提到UIApplicationDelegate,這讓我認爲它並不重要。對於操作系統應該如何知道didEnterRegion是如何實現的以及如何在應用程序處於後臺時如何訪問該類,仍然感到困惑...... –

+0

很確定它基於任何CLLocationManagerDelegate類。該類將被通知任何回調。我就是這樣設立的。我還爲我的位置管理器類創建了一個單例以避免獲得多個回調。 –

0

當您執行了EnterRegion時,您可以發佈本地通知。

即使您在後臺,也會顯示類似警報的彈出窗口。

你可以做一個簡單的測試:

1)創建您的應用程序委託的applicationDidEnterBackground內本地通知對象,任何隨機的消息,並告訴本地通知立即解僱。

2)按下主頁按鈕,當你的應用程序最小化時,你應該看到一個彈出窗口。

+0

感謝您的建議 - 我不熟悉UIApplicationDelegate協議,現在我想知道這不是問題所在。看看我對比爾伯吉斯的評論。 –

0

我認爲你需要去你的應用程序。的plist

並添加所需的背景模式:添加ITME應用註冊了位置更新

和1。如果你的應用程序在後臺,你仍然可以看到頂部的箭頭

和2,如果應用程序被殺害,你仍然可以在頂部看到一個空心箭頭,ios會監控你的區域,但只限於20個區域

2

事情你做錯了:

  1. 背景模式 - 應用程序註冊了位置更新。這不是必需的。當您想要收集位置等重大變化的信息時,這是需要的。因此,請轉到目標>您的應用> Capabilites,然後在背景模式下選擇所需的選項。這會自動爲你更新plist。現在,禁用它。
  2. 您正嘗試在用戶輸入區域時創建警報。雖然此應用程序正在工作時工作,但當您的應用程序處於後臺時,警報無用。 - 而不是觸發本地通知或api調用。

例如,的通知:

-(void)triggerLocalNotification:(CLRegion *)region{ 
    UILocalNotification *notification = [[UILocalNotification alloc]init]; 
    [notification setAlertBody:[NSString stringWithFormat:@"Welcome to %@", [region identifier]]]; 
    [notification setRepeatInterval:0]; 
    [notification setFireDate:[NSDate dateWithTimeIntervalSinceNow:2]]; 
    [notification setTimeZone:[NSTimeZone defaultTimeZone]]; 
    [[UIApplication sharedApplication]scheduleLocalNotification:notification]; 
    NSLog(@"notification triggered with notification %@", notification); 
} 
+0

startMonitoringSignificantLocationChanges and startMonitoringForRegion is work in background mode? –

+0

如果你正在做startMonitoringSignificantLocationChanges,那麼你需要背景模式。當位置發生重大變化時,您需要將應用程序喚醒,並且需要將其告知系統。但是你不需要它來啓動監視區域。無論背景模式如何,startMonitoringForRegion都會調用didEnterRegion和didExitRegion。 –

+0

非常感謝,我想用最少的電池消耗來使用CLLocationManager。 –

相關問題