如何知道最近的iBeacon

我有一个代码知道哪个信标最接近,但是当信标的准确度为-1.00000时,我有一个问题,应用程序采用第二个。

因此,有一个布鲁克寻求最近的灯塔寻找其他人,并将最接近的灯塔与周围的其他灯塔进行比较。 然后,当我知道哪个是最接近的那个时,我向用户显示它的视图,但是当其他信标靠近ipad时,视图接近并且显示视图。

我在iPad上使用iOS 7.1和7.0.4,首先是iPad3,第二个是iPad Mini Retina。

在这里你有代码:

- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region { [self.locationManager startRangingBeaconsInRegion:self.beaconRegion]; } - (void)initRegion { NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:@"00000000-0000-0000-0000-000000000002"]; self.beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid identifier:@"com.devfright.myRegion"]; [self.locationManager startMonitoringForRegion:self.beaconRegion]; } - (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region { NSLog(@"Beacon Found"); [self.locationManager startRangingBeaconsInRegion:self.beaconRegion]; } -(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region { NSLog(@"Left Region"); [self.locationManager stopRangingBeaconsInRegion:self.beaconRegion]; } -(void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region { CLBeacon *beacon = [[CLBeacon alloc] init]; CLBeacon *closestBeacon = [[CLBeacon alloc] init]; closestBeacon = [beacons lastObject]; //Search for the closest and show the view for (int i=0; i<beacons.count; i++) { beacon = beacons[i]; if (beacon.accuracy < closestBeacon.accuracy && beacon.accuracy != -1.000000 && beacon.minor != closestBeacon.minor && beacon.proximity != CLProximityFar) { closestBeacon = beacons[i]; //NSString *closeAccuracy = closestBeacon.minor.stringValue; } NSLog(@"\nActualBeacon:%@\nAccuracy:%f", beacon.minor.stringValue,beacon.accuracy); NSLog(@"\nCloserBeacon: %@\nAccuracy:%f", closestBeacon.minor.stringValue, closestBeacon.accuracy); } NSLog(@"\nClosestBeacon: %@", closestBeacon.minor.stringValue); if (viewShown == NO) { if ([closestBeacon.minor.stringValue isEqual: @"1"]) { actualSection = 1; [self immediateDetection]; }else if ([closestBeacon.minor.stringValue isEqual: @"2"]){ actualSection = 2; [self immediateDetection]; }else if ([closestBeacon.minor.stringValue isEqual: @"3"]){ actualSection = 3; [self immediateDetection]; }else if ([closestBeacon.minor.stringValue isEqual: @"4"]){ actualSection = 4; [self immediateDetection]; }else if ([closestBeacon.minor.stringValue isEqual: @"5"]){ actualSection = 5; [self immediateDetection]; }else if ([closestBeacon.minor.stringValue isEqual: @"6"]){ actualSection = 6; [self immediateDetection]; NSLog(@"6"); }else if ([closestBeacon.minor.stringValue isEqual: @"7"]){ actualSection = 7; [self immediateDetection]; NSLog(@"7"); }else if ([closestBeacon.minor.stringValue isEqual: @"8"]){ actualSection = 8; [self immediateDetection]; NSLog(@"8"); }else if ([closestBeacon.minor.stringValue isEqual: @"9"]){ actualSection = 9; [self immediateDetection]; NSLog(@"9"); }else if ([closestBeacon.minor.stringValue isEqual: @"10"]){ actualSection = 10; [self immediateDetection]; NSLog(@"10"); }else if ([closestBeacon.minor.stringValue isEqual: @"11"]){ actualSection = 11; [self immediateDetection]; NSLog(@"11"); }else if ([closestBeacon.minor.stringValue isEqual: @"30"]){ actualSection = 30; [self immediateDetection]; } } else if (viewShown == YES) { if (closestBeacon.minor.integerValue != actualSection) { //Alarm: Beacon 11 // if (closestBeacon.minor.integerValue != 11 || closestBeacon.minor.integerValue != 10) { [self dismissViewControllerAnimated:NO completion:nil]; //actualSection = 0; viewShown = NO; // } } } } - (void)immediateDetection { viewShown = YES; if (self.presentedViewController) { return; } if (actualSection == 1) { SectionViewController *sectionView = [[SectionViewController alloc] init]; sectionView.section = 1; [self presentViewController:sectionView animated:NO completion:nil]; sectionView.lbl_name.text = self.lbl_name.text; }else if (actualSection == 2){ SectionViewController *sectionView = [[SectionViewController alloc] init]; sectionView.section = 2; [self presentViewController:sectionView animated:NO completion:nil]; sectionView.lbl_name.text = self.lbl_name.text; }else if (actualSection == 3){ SectionViewController *sectionView = [[SectionViewController alloc] init]; sectionView.section = 3; [self presentViewController:sectionView animated:NO completion:nil]; sectionView.lbl_name.text = self.lbl_name.text; }else if (actualSection == 4){ SectionViewController *sectionView = [[SectionViewController alloc] init]; sectionView.section = 4; [self presentViewController:sectionView animated:NO completion:nil]; sectionView.lbl_name.text = self.lbl_name.text; }else if (actualSection == 5){ SectionViewController *sectionView = [[SectionViewController alloc] init]; sectionView.section = 5; [self presentViewController:sectionView animated:NO completion:nil]; sectionView.lbl_name.text = self.lbl_name.text; }else if (actualSection == 6){ SectionViewController *sectionView = [[SectionViewController alloc] init]; sectionView.section = 6; [self presentViewController:sectionView animated:NO completion:nil]; sectionView.lbl_name.text = self.lbl_name.text; }else if (actualSection == 7){ SectionViewController *sectionView = [[SectionViewController alloc] init]; sectionView.section = 7; [self presentViewController:sectionView animated:NO completion:nil]; sectionView.lbl_name.text = self.lbl_name.text; }else if (actualSection == 8){ SectionViewController *sectionView = [[SectionViewController alloc] init]; sectionView.section = 8; [self presentViewController:sectionView animated:NO completion:nil]; sectionView.lbl_name.text = self.lbl_name.text; }else if (actualSection == 9){ SectionViewController *sectionView = [[SectionViewController alloc] init]; sectionView.section = 9; [self presentViewController:sectionView animated:NO completion:nil]; sectionView.lbl_name.text = self.lbl_name.text; }else if (actualSection == 10){ ThiefAlarmViewController *thiefAlarmView = [[ThiefAlarmViewController alloc] init]; [self presentViewController:thiefAlarmView animated:NO completion:nil]; }else if (actualSection == 11){ ThiefAlarmViewController *thiefAlarmView = [[ThiefAlarmViewController alloc] init]; [self presentViewController:thiefAlarmView animated:NO completion:nil]; }else if (actualSection == 30){ SectionViewController *sectionView = [[SectionViewController alloc] init]; sectionView.section = 30; [self presentViewController:sectionView animated:NO completion:nil]; sectionView.lbl_name.text = self.lbl_name.text; } } 

当我知道最近的iBeacon时,我会显示它的视图,但是当它的准确度为-1.00000并且与其他人相比时,应用程序采用第二个,因为第一个具有准确度= -1.00000。

希望任何人都可以帮助我,因为我不知道该怎么做,也许这是一个iBeacon问题,但我认为这个问题有一个解决方案。

谢谢。

首先:替换你的long else/if of locationManager:didRangeBeacons:inRegion: with:

 if (([closestBeacon.minor intValue] > 0 && [closestBeacon.minor intValue] <= 11) || [closestBeacon.minor intValue] == 30) { actualSection = [closestBeacon.minor intValue]; [self immediateDetection]; } 

immediateDetection替换你的long else/if

 if ((actualSection > 0 && actualSection < 10 || actualSection == 30) { SectionViewController *sectionView = [[SectionViewController alloc] init]; sectionView.section = actualSection; [self presentViewController:sectionView animated:NO completion:nil]; sectionView.lbl_name.text = self.lbl_name.text; } else if (actualSection == 10 || actualSection == 11) { ThiefAlarmViewController *thiefAlarmView = [[ThiefAlarmViewController alloc] init]; [self presentViewController:thiefAlarmView animated:NO completion:nil]; } else { } 

这应该可以为您节省大量代码。

对于您的问题,您可以这样:

  NSPredicate *predicateIrrelevantBeacons = [NSPredicate predicateWithFormat:@"(self.accuracy != -1) AND ((self.proximity != %d) OR (self.proximity != %d))", CLProximityFar,CLProximityUnknown]; NSArray *relevantsBeacons = [beacons filteredArrayUsingPredicate: predicateIrrelevantBeacons]; NSPredicate *predicateMin = [NSPredicate predicateWithFormat:@"self.accuracy == %@.@min.accuracy", relevantsBeacons]; CLBeacon *closestBeacon = nil; NSArray *closestArray = [[relevantsBeacons filteredArrayUsingPredicate:predicateMin]; if ([closestArray count] > 0) closestBeacon = [closestArray objectAtIndex:0]; if (closestBeacon) { //Do your thing } else {//No relevant close beacon} 

locationManager:didRangeBeacons:inRegion:将返回接近顺序的信标列表。 也就是说,列表中的第一个信标将是离您最近的。

但是,此规则有一个例外:如果任何信标接近未知,则它们将位于列表的顶部(因为它们的准确度为-1)。 为了解决这个问题,只需过滤掉任何未知信标,然后选择列表中的第一个:

 beacons = [beacons filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"proximity != %d", CLProximityUnknown]]; CLBeacon *nearestBeacon = [beacons firstObject]; 

除了过滤接近值-1之外,您还必须考虑某些iBeacons定期不出现在didRangeBeacons: inRegion的回调中的didRangeBeacons: inRegion 。 这可能由于无线电干扰而发生,特别是对于不经常发送广告的电池供电的信标。

要解决此问题,您需要保留自己最近看过的信标列表,并跟踪在过去几秒钟内看到的任何信标。 如果其中一个信标的接近度为-1,则可以不将其放入列表中,或者如果不存在,则重新使用上一个已知的非-1接近值。

您需要考虑的另一个考虑因素是接近值会在很大程度上反弹。 您可能需要为算法添加一些滞后逻辑,以便最接近的信标不会每秒来回反弹。 您希望如何执行此操作的具体细节取决于您的用例。

Swift 4.0 iOS 11.x.

James Frost的回答现在写成……

 let beacons2S = beacons.filter { $0.proximity != CLProximity.unknown } 

这意味着使信标2S设置所有信标,不包括未知接近的信标。 令人惊讶的是,苹果公司还没有修复这个function,它会让每个人以及任何使用ibeacons尝试代码的人都知道。