@interface XBBeaconViewController()  @property (nonatomic, strong) id locationManagerObserver;  @end	

@implementation XBBeaconViewController   - (void)viewDidLoad {    [super viewDidLoad];    [self.tableView reloadData];    [self initObservers]; }  - (void)dealloc {    [[NSNotificationCenter defaultCenter] removeObserver:self.observer]; }  - (void)initObservers {    // TODO }  #pragma mark - Table View  - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {    static NSString *NoVisibleBeaconCellIdentifier = @"NoVisibleBeaconCell";    static NSString *BeaconCellIdentifier = @"BeaconCell";    // TODO }  - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {    // TODO }  @end	

#import <Foundation/Foundation.h> #import <CoreLocation/CoreLocation.h>  extern NSString * const XBBeaconLocationManagerValueChangedNotification;  @interface XBBeaconLocationManager : NSObject <CLLocationManagerDelegate>  + (XBBeaconLocationManager *)sharedManager;  @property (nonatomic, readonly) NSArray *allBeacons;  @end	

NSString * const XBBeaconLocationManagerValueChangedNotification = @"XBBeaconLocationManagerValueChangedNotification";  @interface XBBeaconLocationManager () <UIAlertViewDelegate>  @property (nonatomic, strong) CLLocationManager *locationManager;  @property (nonatomic, strong) NSArray *allRegions;  @property (nonatomic, strong) NSMutableArray *currentBeacons;  @end	

@implementation XBBeaconLocationManager	

+ (XBBeaconLocationManager *)sharedManager {    static XBBeaconLocationManager *sharedManager = nil;    static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{        sharedManager = [[self alloc] init];    });    return sharedManager; }	

- (instancetype)init { if (self = [super init]) {   [self initAccordingToAuthorizationStatus]; } return self; }  	

- (void)initAccordingToAuthorizationStatus {    if ([CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorized) {        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Activer iBeacon ?", @"Activer iBeacon ?”) message:NSLocalizedString(@“Authoriser l’accès à vos donnés de localisation ?”, nil) delegate:self cancelButtonTitle:NSLocalizedString(@"Non", @“Non") otherButtonTitles:NSLocalizedString(@"Oui, continuer", @"Oui, continuer"), nil];        [alertView show];     } else if ([CLLocationManager authorizationStatus] != kCLAuthorizationStatusDenied           && [CLLocationManager authorizationStatus] != kCLAuthorizationStatusRestricted) {        [self initialize];        return;    } }  - (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex {    if (buttonIndex == 1) {        [self initialize];    } }	

- (void)initialize {    [self initializeLocationManager];    [self initBeaconRegions]; }	

- (void)initBeaconRegions { 	CLBeaconRegion *beacon = [[CLBeaconRegion alloc] initWithProximityUUID: 		[[NSUUID alloc] initWithUUIDString:@“B9407F30-F5F8-466E-AFF9-25556B57FE6D"]                                identifier:@"Xebia Beacon Region"];     // Ajouter plus de beacons si nécessaire    self.allRegions = @[beacon];     for (CLBeaconRegion *region in self.allRegions) {        [self.locationManager startMonitoringForRegion:region];        [self.locationManager requestStateForRegion:region];    } }  	

- (void)initializeLocationManager { 	// Initialise un nouveau Location Manager 	self.locationManager = [[CLLocationManager alloc] init]; 	self.locationManager.delegate = self; } 	

#pragma mark - CLLocationManagerDelegate  - (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region {  	if (manager != self.locationManager) { 		return; 	}      	if (state == CLRegionStateInside) { 		[self startBeaconRangingInRegion:region]; 	}  	else if (state == CLRegionStateOutside) { 		[self stopBeaconRangingInRegion:region]; 	} }   - (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region { 	if (manager != self.locationManager) { 		return; 	}  	[self postValueChangedNotification]; 	[self startBeaconRangingInRegion:region]; }  - (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region { 	if (manager != self.locationManager) { 		return; 	} 	[self postValueChangedNotification]; 	[self stopBeaconRangingInRegion:region]; }	

- (void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region { 	self.currentBeacons = [NSMutableArray array];     // Trouve le beacon le plus proche 	if ([beacons count] > 0) { 		CLBeacon *closestBeacon = beacons[0]; 		if (closestBeacon.proximity == CLProximityImmediate) { 			[self.currentBeacons addObject:closestBeacon]; 			[self postValueChangedNotification]; 		}  		// Trouve les autres beacons 		else if (closestBeacon.proximity == CLProximityNear) { 			[self.currentBeacons addObject:closestBeacon]; 			[self postValueChangedNotification]; 		} 		 		else { 			[self.currentBeacons addObject:closestBeacon]; 			[self postValueChangedNotification]; 		} 	}    // Aucun beacon n'a été trouvé - le signal a été perdu 	else {   		[self postValueChangedNotification];   		return; 	} }	

- (void)locationManager:(CLLocationManager *)manager rangingBeaconsDidFailForRegion:(CLBeaconRegion *)region withError:(NSError *)error { 	[self postValueChangedNotification];  	if (error.description) { 		NSLog(@"Location error while ranging. Description: %@", error.description); 	} } - (void)locationManager:(CLLocationManager *)manager monitoringDidFailForRegion:(CLRegion *)region withError:(NSError *)error { 	[self postValueChangedNotification]; 	if (error.description) { 		NSLog(@"Location error while monitoring. Description: %@", error.description); 	} }	

- (void)startBeaconRangingInRegion:(CLRegion *)region { 	[self.locationManager startRangingBeaconsInRegion:(CLBeaconRegion *)region]; }  - (void)stopBeaconRangingInRegion:(CLRegion *)region { 	[self.locationManager stopRangingBeaconsInRegion:(CLBeaconRegion *)region]; } 	
Implémentons maintenant les méthodes postValueChangedNotifications et allBeacons. La première envoie à l’aide du NSNotificationCenter une nouvelle notification de nom postNotificationName:XBBeaconLocationManagerValueChangedNotification, tandis que la seconde fournit un accès externe à la liste des beacons calculée précédemment. 
- (void)postValueChangedNotification { 	[[NSNotificationCenter defaultCenter] postNotificationName:XBBeaconLocationManagerValueChangedNotification object:nil userInfo:nil]; }  - (NSArray *)allBeacons {    return _currentBeacons; } 	

- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status { 	if (status == kCLAuthorizationStatusAuthorized) { 		[self initialize]; 	} else if (status == kCLAuthorizationStatusDenied) { 		[[[UIAlertView alloc] initWithTitle:nil                               message:NSLocalizedString(@"Merci d'activer les services de localisation.", nil)                              delegate:nil                     cancelButtonTitle:nil                     otherButtonTitles:@"OK", nil] show]; 	} } @end 	

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    [self initBeaconTracking];    return YES; } - (void)initBeaconTracking {    [XBBeaconLocationManager sharedManager]; }  	

- (void)initObservers {    __weak typeof(self) weakSelf = self;    self.locationManagerObserver = [[NSNotificationCenter defaultCenter] addObserverForName:XBBeaconLocationManagerValueChangedNotification object:nil queue:nil usingBlock:^(NSNotification *note) {        [weakSelf.tableView reloadData];    }]; } 	

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {    static NSString *NoVisibleBeaconCellIdentifier = @"NoVisibleBeaconCell";    static NSString *BeaconCellIdentifier = @"BeaconCell";    NSArray *allBeacons = [XBBeaconLocationManager sharedManager].allBeacons;         UITableViewCell *cell;     if ([allBeacons count] > 0) {        cell = [tableView dequeueReusableCellWithIdentifier:BeaconCellIdentifier];        CLBeacon *beacon = allBeacons[indexPath.row];        cell.textLabel.text = [[beacon proximityUUID] UUIDString];        cell.detailTextLabel.text = [NSString stringWithFormat:@"maj: %@, min: %@, dist: %.2fm", [beacon.major stringValue], [beacon.minor stringValue], beacon.accuracy];    } else {        cell = [tableView dequeueReusableCellWithIdentifier:NoVisibleBeaconCellIdentifier];    }     return cell; }  	

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {    NSInteger allBeacons = [[XBBeaconLocationManager sharedManager].allBeacons count];    return allBeacons ? allBeacons : 1; }