2

ユーザーが家を出たときに通知を発するアプリをまとめています。そこで、半径25の領域監視を実装しました。私が抱えている問題は、シミュレーション時(iPhoneシミュレーター5.0)で、領域境界を設定するカスタムの場所(ホーム)を設定することです。次に、地域の境界の外側、つまり通りの終わりに別のカスタムの場所を入力します。ただし、アプリはリージョンの終了を登録しません。自宅の場所と地域を設定してからApple本社に変更した場合にのみ、登録されて通知が送信されます。バックグラウンドモードでは、アプリは大幅な場所の変更に切り替わります。ただし、フォアグラウンドまたはバックグラウンドで同じ問題が発生します。「リマインダー」アプリのように、私が探しているのは、アプリが地域の境界を出たり出たりした直後、つまり通りの終わりまで歩いた直後に通知を発することです。

これが私のviewcontroller.mファイルの一部です:

- (void)viewDidLoad {
    [super viewDidLoad];

  // Create empty array to add region events to.
  updateEvents = [[NSMutableArray alloc] initWithCapacity:0];

  // Create location manager with filters set for battery efficiency.
  locationManager = [[CLLocationManager alloc] init];
  locationManager.delegate = self;
  locationManager.distanceFilter = kCLLocationAccuracyBest; //could try KLDistanceFilterNone;
  locationManager.desiredAccuracy = kCLLocationAccuracyBest;

  // Start updating location changes.
          [locationManager startUpdatingLocation];
}

- (void)viewDidAppear:(BOOL)animated {
  // Get all regions being monitored for this application.
  NSArray *regions = [[locationManager monitoredRegions] allObjects];

  // Iterate through the regions and add annotations to the map for each of them.
          for (int i = 0; i < [regions count]; i++) {
                    CLRegion *region = [regions objectAtIndex:i];
  RegionAnnotation *annotation = [[RegionAnnotation alloc] initWithCLRegion:region];
                    [regionsMapView addAnnotation:annotation];
                    [annotation release];
          }
}

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
  NSLog(@"didFailWithError: %@", error);
}


- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
  NSLog(@"didUpdateToLocation %@ from %@", newLocation, oldLocation);

  // Work around a bug in MapKit where user location is not initially zoomed to.
          if (oldLocation == nil) {
  // Zoom to the current user location.
                    MKCoordinateRegion userLocation = MKCoordinateRegionMakeWithDistance(newLocation.coordinate, 100.0, 100.0);
                    [regionsMapView setRegion:userLocation animated:YES];
          }
}


- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region  {
  NSString *event = [NSString stringWithFormat:@"didEnterRegion %@ at %@", region.identifier, [NSDate date]];

          [self updateWithEvent:event];
}


- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region {
  NSString *event = [NSString stringWithFormat:@"didExitRegion %@ at %@", region.identifier, [NSDate date]];
          [self updateWithEvent:event];
//implement local notification:
    UIApplication *app                = [UIApplication sharedApplication];
    UILocalNotification *notification = [[UILocalNotification alloc] init];
    [[UIApplication sharedApplication] cancelAllLocalNotifications];

    if (notification == nil)
        return;
    notification.alertBody = [NSString stringWithFormat:@"Did You Lock Your House?"];
    notification.alertAction = @"Lock House";
    notification.soundName = UILocalNotificationDefaultSoundName;
    notification.applicationIconBadgeNumber = 1;
    [app presentLocalNotificationNow:notification];

    [notification release];
// ends here

//following is an alert for the case of exiting boundary whilst app is in foreground
    UIAlertView *alr=[[UIAlertView alloc] initWithTitle:@"Reminder didExitRegion" message:region.identifier delegate:nil cancelButtonTitle:nil otherButtonTitles:@"Ok",nil];

    [alr show];

    [alr release];
    //ends here
}

- (void)locationManager:(CLLocationManager *)manager monitoringDidFailForRegion:(CLRegion *)region withError:(NSError *)error {
  NSString *event = [NSString stringWithFormat:@"monitoringDidFailForRegion %@: %@", region.identifier, error];

          [self updateWithEvent:event];
}

- (IBAction)addRegion {
  if ([CLLocationManager regionMonitoringAvailable]) {
  // Create a new region based on the center of the map view.
  CLLocationCoordinate2D coord = CLLocationCoordinate2DMake(regionsMapView.centerCoordinate.latitude, regionsMapView.centerCoordinate.longitude);
  CLRegion *newRegion = [[CLRegion alloc] initCircularRegionWithCenter:coord
                                                                                                                                                                              radius:25.0
                                                                                                                                                                   identifier:[NSString stringWithFormat:@"%f, %f", regionsMapView.centerCoordinate.latitude, regionsMapView.centerCoordinate.longitude]];

  // Create an annotation to show where the region is located on the map.
                    RegionAnnotation *myRegionAnnotation = [[RegionAnnotation alloc] initWithCLRegion:newRegion];
                    myRegionAnnotation.coordinate = newRegion.center;
                    myRegionAnnotation.radius = newRegion.radius;

                    [regionsMapView addAnnotation:myRegionAnnotation];

                    [myRegionAnnotation release];

  // Start monitoring the newly created region.
                    [locationManager startMonitoringForRegion:newRegion desiredAccuracy:kCLLocationAccuracyBest];

                    [newRegion release];
          }
  else {
  NSLog(@"Region monitoring is not available.");
          }
}

この作品は「地域」テンプレートから派生しています。

4

2 に答える 2

6

iOS シミュレーターは、exit/enter を使用したジオフェンスの更新が苦手なことで有名です。これを確認できる 1 つの方法は、アプリのジオフェンスを現在の場所に設定することです。次に、iOS シミュレーターのデバッグ メニューから、[場所]、[Freeway Drive] の順に押します。これで、デバイスは高速道路の運転をシミュレートします。シミュレーターが私のようなものである場合、didExitRegion イベントを登録しません。

なんで?地域は、ほとんどの場合、Wi-Fi、携帯電話基地局、および位置情報を要求する電話のその他のアプリケーションを使用する Apple の隠しアルゴリズムによって決定されます。シミュレーターが Wi-Fi や携帯電話基地局を使用していないことを考えると、地域の監視はかなり不可能になるでしょう。

領域の終了後にコードの残りの部分が機能しているかどうかをテストするには、locationManager:didExitRegion: メソッドを手動で起動するボタンまたは何かを作成できます。また、プロジェクトをデバイスに接続してコンパイルし、iPhone シミュレーターから iOS デバイスに変更することを強くお勧めします。次に、デバイスのプラグを抜き、スマートフォンからアプリを実行してテストできます。

于 2012-08-03T17:17:59.823 に答える
1

それはあなたが得る最高の精度です。地域マッチングはセルタワーの三角測量のみを使用するため、密度の高い地域では 50 ~ 100 m でトリガーされる可能性があり、疎な地域では数百メートルかかる場合があります。

より詳細な情報が必要な場合は、直接位置情報サービスを使用する必要があります. しかし、それはバッテリーを消費するので、あなたの毒を選んでください.

于 2012-04-25T00:37:28.527 に答える