Improve UI and remove potential for duplicate
beacons
diff --git a/HiBeacons/Main.storyboard b/HiBeacons/Main.storyboard
index 4b675f8..63388de 100644
--- a/HiBeacons/Main.storyboard
+++ b/HiBeacons/Main.storyboard
@@ -16,30 +16,34 @@
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
- <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="Cds-q7-g9T">
- <rect key="frame" x="251" y="504" width="51" height="31"/>
- <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
- </switch>
- <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" placeholderIntrinsicWidth="177" placeholderIntrinsicHeight="21" text="Enable beacon ranging" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="U3w-jj-HVl">
- <rect key="frame" x="20" y="509" width="177" height="21"/>
- <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
- <fontDescription key="fontDescription" type="system" pointSize="17"/>
- <nil key="highlightedColor"/>
- </label>
- <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="8Ua-PS-yVS">
- <rect key="frame" x="251" y="465" width="51" height="31"/>
- <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
- </switch>
- <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" placeholderIntrinsicWidth="203" placeholderIntrinsicHeight="21" text="Enable beacon advertising" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="MnH-3s-6S0">
- <rect key="frame" x="20" y="470" width="203" height="21"/>
- <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
- <fontDescription key="fontDescription" type="system" pointSize="17"/>
- <nil key="highlightedColor"/>
- </label>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="default" rowHeight="44" sectionHeaderHeight="10" sectionFooterHeight="10" translatesAutoresizingMaskIntoConstraints="NO" id="CS9-7M-geh">
- <rect key="frame" x="0.0" y="64" width="320" height="393"/>
+ <rect key="frame" x="0.0" y="64" width="320" height="504"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
+ <prototypes>
+ <tableViewCell contentMode="scaleToFill" selectionStyle="none" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="OperationCell" id="ed8-eW-a13">
+ <rect key="frame" x="0.0" y="55" width="320" height="44"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="ed8-eW-a13" id="8Lt-Vb-O3A">
+ <rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <subviews>
+ <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="8Ua-PS-yVS">
+ <rect key="frame" x="251" y="6" width="51" height="31"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+ </switch>
+ </subviews>
+ <constraints>
+ <constraint firstAttribute="trailing" secondItem="8Ua-PS-yVS" secondAttribute="trailing" constant="20" symbolic="YES" id="JPb-oj-TFB"/>
+ <constraint firstItem="8Ua-PS-yVS" firstAttribute="centerY" secondItem="8Lt-Vb-O3A" secondAttribute="centerY" id="Pyg-Uy-VDb"/>
+ </constraints>
+ </tableViewCellContentView>
+ <connections>
+ <outlet property="accessoryView" destination="8Ua-PS-yVS" id="NLf-S0-v40"/>
+ </connections>
+ </tableViewCell>
+ </prototypes>
+ <sections/>
<connections>
<outlet property="dataSource" destination="vXZ-lx-hvc" id="Czn-Td-yrn"/>
<outlet property="delegate" destination="vXZ-lx-hvc" id="ue4-SY-ipJ"/>
@@ -55,29 +59,17 @@
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
- <constraint firstAttribute="centerX" secondItem="Cds-q7-g9T" secondAttribute="centerX" constant="-115.5" id="4kH-LM-eLD"/>
<constraint firstItem="YTO-vF-9qf" firstAttribute="leading" secondItem="CS9-7M-geh" secondAttribute="leading" id="4zl-zx-S2j"/>
- <constraint firstItem="U3w-jj-HVl" firstAttribute="centerY" secondItem="Cds-q7-g9T" secondAttribute="centerY" id="6es-J3-bPP"/>
- <constraint firstItem="U3w-jj-HVl" firstAttribute="leading" secondItem="kh9-bI-dsS" secondAttribute="leading" priority="250" constant="20" symbolic="YES" id="9Vr-p8-IMt"/>
- <constraint firstItem="8Ua-PS-yVS" firstAttribute="top" secondItem="CS9-7M-geh" secondAttribute="bottom" constant="8" symbolic="YES" id="ArV-qK-yKz"/>
- <constraint firstItem="TQk-42-Sf6" firstAttribute="top" secondItem="U3w-jj-HVl" secondAttribute="bottom" constant="38" id="Av2-TH-mco"/>
- <constraint firstItem="U3w-jj-HVl" firstAttribute="leading" secondItem="MnH-3s-6S0" secondAttribute="leading" id="AwR-qf-gC3"/>
<constraint firstItem="CS9-7M-geh" firstAttribute="top" secondItem="fQI-hj-WaS" secondAttribute="bottom" constant="44" id="DDy-X3-nyF"/>
+ <constraint firstItem="TQk-42-Sf6" firstAttribute="top" secondItem="CS9-7M-geh" secondAttribute="bottom" id="Fe8-x4-2Zl"/>
<constraint firstItem="YTO-vF-9qf" firstAttribute="trailing" secondItem="CS9-7M-geh" secondAttribute="trailing" id="IPO-G2-Cfs"/>
<constraint firstItem="YTO-vF-9qf" firstAttribute="bottom" secondItem="CS9-7M-geh" secondAttribute="top" id="M1b-hE-8Mu"/>
<constraint firstItem="CS9-7M-geh" firstAttribute="leading" secondItem="kh9-bI-dsS" secondAttribute="leading" id="M8a-U0-Br2"/>
- <constraint firstItem="Cds-q7-g9T" firstAttribute="top" secondItem="8Ua-PS-yVS" secondAttribute="bottom" constant="8" symbolic="YES" id="MQi-80-NxX"/>
<constraint firstAttribute="trailing" secondItem="CS9-7M-geh" secondAttribute="trailing" id="U0b-9i-hL0"/>
- <constraint firstItem="U3w-jj-HVl" firstAttribute="top" secondItem="MnH-3s-6S0" secondAttribute="bottom" constant="18" id="VPr-k1-4Dt"/>
- <constraint firstItem="8Ua-PS-yVS" firstAttribute="leading" secondItem="MnH-3s-6S0" secondAttribute="trailing" constant="28" id="gAQ-Re-p14"/>
- <constraint firstItem="Cds-q7-g9T" firstAttribute="leading" secondItem="U3w-jj-HVl" secondAttribute="trailing" constant="54" id="jjn-kL-ZL9"/>
- <constraint firstItem="8Ua-PS-yVS" firstAttribute="leading" secondItem="Cds-q7-g9T" secondAttribute="leading" id="qOJ-88-znE"/>
</constraints>
</view>
<connections>
- <outlet property="advertisingSwitch" destination="8Ua-PS-yVS" id="Xji-pb-0Zv"/>
<outlet property="beaconTableView" destination="CS9-7M-geh" id="hb4-1u-FP4"/>
- <outlet property="rangingSwitch" destination="Cds-q7-g9T" id="kMu-Vm-wZg"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="x5A-6p-PRh" sceneMemberID="firstResponder"/>
diff --git a/HiBeacons/NTViewController.h b/HiBeacons/NTViewController.h
index 18531d9..1ee4e2d 100644
--- a/HiBeacons/NTViewController.h
+++ b/HiBeacons/NTViewController.h
@@ -30,8 +30,6 @@
@interface NTViewController : UIViewController <CLLocationManagerDelegate, CBPeripheralManagerDelegate,
UITableViewDataSource, UITableViewDelegate>
-@property (nonatomic, weak) IBOutlet UISwitch *advertisingSwitch;
-@property (nonatomic, weak) IBOutlet UISwitch *rangingSwitch;
@property (nonatomic, weak) IBOutlet UITableView *beaconTableView;
@end
diff --git a/HiBeacons/NTViewController.m b/HiBeacons/NTViewController.m
index 9b7c08e..73304df 100644
--- a/HiBeacons/NTViewController.m
+++ b/HiBeacons/NTViewController.m
@@ -28,7 +28,29 @@
static NSString * const kUUID = @"00000000-0000-0000-0000-000000000000";
static NSString * const kIdentifier = @"SomeIdentifier";
-static NSString * const kCellIdentifier = @"BeaconCell";
+
+static NSString * const kOperationCellIdentifier = @"OperationCell";
+static NSString * const kBeaconCellIdentifier = @"BeaconCell";
+
+static NSString * const kAdvertisingOperationTitle = @"Advertising";
+static NSString * const kRangingOperationTitle = @"Ranging";
+static NSUInteger const kNumberOfSections = 2;
+static NSUInteger const kNumberOfAvailableOperations = 2;
+static CGFloat const kOperationCellHeight = 44;
+static CGFloat const kBeaconCellHeight = 52;
+static NSString * const kBeaconSectionTitle = @"Looking for beacons...";
+static CGPoint const kActivityIndicatorPosition = (CGPoint){205, 12};
+static NSString * const kBeaconsHeaderViewIdentifier = @"BeaconsHeader";
+
+typedef NS_ENUM(NSUInteger, NTSectionType) {
+ NTOperationsSection,
+ NTDetectedBeaconsSection
+};
+
+typedef NS_ENUM(NSUInteger, NTOperationsRow) {
+ NTAdvertisingRow,
+ NTRangingRow
+};
@interface NTViewController ()
@@ -36,23 +58,13 @@
@property (nonatomic, strong) CLBeaconRegion *beaconRegion;
@property (nonatomic, strong) CBPeripheralManager *peripheralManager;
@property (nonatomic, strong) NSArray *detectedBeacons;
+@property (nonatomic, weak) UISwitch *advertisingSwitch;
+@property (nonatomic, weak) UISwitch *rangingSwitch;
@end
@implementation NTViewController
-- (void)viewDidLoad
-{
- [super viewDidLoad];
-
- [self.advertisingSwitch addTarget:self
- action:@selector(changeAdvertisingState:)
- forControlEvents:UIControlEventValueChanged];
- [self.rangingSwitch addTarget:self
- action:@selector(changeRangingState:)
- forControlEvents:UIControlEventValueChanged];
-}
-
#pragma mark - Beacon ranging
- (void)createBeaconRegion
{
@@ -99,6 +111,8 @@
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
+ self.detectedBeacons = [NSArray array];
+
[self turnOnRanging];
}
@@ -110,13 +124,118 @@
}
[self.locationManager stopRangingBeaconsInRegion:self.beaconRegion];
+
+ NSIndexSet *deletedSections = [self deletedSections];
+ self.detectedBeacons = [NSArray array];
- self.detectedBeacons = nil;
- [self.beaconTableView reloadData];
+ [self.beaconTableView beginUpdates];
+ if (deletedSections)
+ [self.beaconTableView deleteSections:deletedSections withRowAnimation:UITableViewRowAnimationFade];
+ [self.beaconTableView endUpdates];
NSLog(@"Turned off ranging.");
}
+#pragma mark - Index path management
+- (NSArray *)indexPathsOfRemovedBeacons:(NSArray *)beacons
+{
+ NSMutableArray *indexPaths = nil;
+
+ NSUInteger row = 0;
+ for (CLBeacon *existingBeacon in self.detectedBeacons) {
+ BOOL stillExists = NO;
+ for (CLBeacon *beacon in beacons) {
+ if ((existingBeacon.major.integerValue == beacon.major.integerValue) &&
+ (existingBeacon.minor.integerValue == beacon.minor.integerValue)) {
+ stillExists = YES;
+ break;
+ }
+ }
+ if (!stillExists) {
+ if (!indexPaths)
+ indexPaths = [NSMutableArray new];
+ [indexPaths addObject:[NSIndexPath indexPathForRow:row inSection:NTDetectedBeaconsSection]];
+ }
+ row++;
+ }
+
+ return indexPaths;
+}
+
+- (NSArray *)indexPathsOfInsertedBeacons:(NSArray *)beacons
+{
+ NSMutableArray *indexPaths = nil;
+
+ NSUInteger row = 0;
+ for (CLBeacon *beacon in beacons) {
+ BOOL isNewBeacon = YES;
+ for (CLBeacon *existingBeacon in self.detectedBeacons) {
+ if ((existingBeacon.major.integerValue == beacon.major.integerValue) &&
+ (existingBeacon.minor.integerValue == beacon.minor.integerValue)) {
+ isNewBeacon = NO;
+ break;
+ }
+ }
+ if (isNewBeacon) {
+ if (!indexPaths)
+ indexPaths = [NSMutableArray new];
+ [indexPaths addObject:[NSIndexPath indexPathForRow:row inSection:NTDetectedBeaconsSection]];
+ }
+ row++;
+ }
+
+ return indexPaths;
+}
+
+- (NSArray *)indexPathsForBeacons:(NSArray *)beacons
+{
+ NSMutableArray *indexPaths = [NSMutableArray new];
+ for (NSUInteger row = 0; row < beacons.count; row++) {
+ [indexPaths addObject:[NSIndexPath indexPathForRow:row inSection:NTDetectedBeaconsSection]];
+ }
+
+ return indexPaths;
+}
+
+- (NSIndexSet *)insertedSections
+{
+ if (self.rangingSwitch.on && [self.beaconTableView numberOfSections] == kNumberOfSections - 1) {
+ return [NSIndexSet indexSetWithIndex:1];
+ } else {
+ return nil;
+ }
+}
+
+- (NSIndexSet *)deletedSections
+{
+ if (!self.rangingSwitch.on && [self.beaconTableView numberOfSections] == kNumberOfSections) {
+ return [NSIndexSet indexSetWithIndex:1];
+ } else {
+ return nil;
+ }
+}
+
+- (NSArray *)filteredBeacons:(NSArray *)beacons
+{
+ // Filters duplicate beacons out; this may happen temporarily if the originating device changes its Bluetooth id
+ NSMutableArray *mutableBeacons = [beacons mutableCopy];
+
+ NSMutableSet *lookup = [[NSMutableSet alloc] init];
+ for (int index = 0; index < [beacons count]; index++) {
+ CLBeacon *curr = [beacons objectAtIndex:index];
+ NSString *identifier = [NSString stringWithFormat:@"%@/%@", curr.major, curr.minor];
+
+ // this is very fast constant time lookup in a hash table
+ if ([lookup containsObject:identifier]) {
+ [mutableBeacons removeObjectAtIndex:index];
+ } else {
+ [lookup addObject:identifier];
+ }
+ }
+
+ return [mutableBeacons copy];
+}
+
#pragma mark - Beacon ranging delegate methods
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
@@ -125,7 +244,7 @@
self.rangingSwitch.on = NO;
return;
}
-
+
if ([CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorized) {
NSLog(@"Couldn't turn on ranging: Location services not authorised.");
self.rangingSwitch.on = NO;
@@ -138,14 +257,37 @@
- (void)locationManager:(CLLocationManager *)manager
didRangeBeacons:(NSArray *)beacons
inRegion:(CLBeaconRegion *)region {
- if ([beacons count] == 0) {
+ NSArray *filteredBeacons = [self filteredBeacons:beacons];
+
+ if (filteredBeacons.count == 0) {
NSLog(@"No beacons found nearby.");
} else {
- NSLog(@"Found %lu %@.", (unsigned long)[beacons count], [beacons count] > 1 ? @"beacons" : @"beacon");
+ NSLog(@"Found %lu %@.", (unsigned long)[filteredBeacons count],
+ [filteredBeacons count] > 1 ? @"beacons" : @"beacon");
}
- self.detectedBeacons = beacons;
- [self.beaconTableView reloadData];
+ NSIndexSet *insertedSections = [self insertedSections];
+ NSIndexSet *deletedSections = [self deletedSections];
+ NSArray *deletedRows = [self indexPathsOfRemovedBeacons:filteredBeacons];
+ NSArray *insertedRows = [self indexPathsOfInsertedBeacons:filteredBeacons];
+ NSArray *reloadedRows = nil;
+ if (!deletedRows && !insertedRows)
+ reloadedRows = [self indexPathsForBeacons:filteredBeacons];
+
+ self.detectedBeacons = filteredBeacons;
+
+ [self.beaconTableView beginUpdates];
+ if (insertedSections)
+ [self.beaconTableView insertSections:insertedSections withRowAnimation:UITableViewRowAnimationFade];
+ if (deletedSections)
+ [self.beaconTableView deleteSections:deletedSections withRowAnimation:UITableViewRowAnimationFade];
+ if (insertedRows)
+ [self.beaconTableView insertRowsAtIndexPaths:insertedRows withRowAnimation:UITableViewRowAnimationFade];
+ if (deletedRows)
+ [self.beaconTableView deleteRowsAtIndexPaths:deletedRows withRowAnimation:UITableViewRowAnimationFade];
+ if (reloadedRows)
+ [self.beaconTableView reloadRowsAtIndexPaths:reloadedRows withRowAnimation:UITableViewRowAnimationNone];
+ [self.beaconTableView endUpdates];
}
#pragma mark - Beacon advertising
@@ -226,51 +368,131 @@
}
#pragma mark - Table view functionality
-- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
+- (NSString *)detailsStringForBeacon:(CLBeacon *)beacon
{
- CLBeacon *beacon = self.detectedBeacons[indexPath.row];
-
- UITableViewCell *defaultCell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
- reuseIdentifier:kCellIdentifier];
-
- defaultCell.textLabel.text = beacon.proximityUUID.UUIDString;
-
- NSString *proximityString;
+ NSString *proximity;
switch (beacon.proximity) {
case CLProximityNear:
- proximityString = @"Near";
+ proximity = @"Near";
break;
case CLProximityImmediate:
- proximityString = @"Immediate";
+ proximity = @"Immediate";
break;
case CLProximityFar:
- proximityString = @"Far";
+ proximity = @"Far";
break;
case CLProximityUnknown:
default:
- proximityString = @"Unknown";
+ proximity = @"Unknown";
break;
}
- defaultCell.detailTextLabel.text = [NSString stringWithFormat:@"%@, %@ • %@ • %f • %li",
- beacon.major.stringValue, beacon.minor.stringValue, proximityString, beacon.accuracy, (long)beacon.rssi];
- defaultCell.detailTextLabel.textColor = [UIColor grayColor];
- return defaultCell;
+ NSString *format = @"%@, %@ • %@ • %f • %li";
+ return [NSString stringWithFormat:format, beacon.major, beacon.minor, proximity, beacon.accuracy, beacon.rssi];
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
+{
+ UITableViewCell *cell = nil;
+ switch (indexPath.section) {
+ case NTOperationsSection: {
+ cell = [tableView dequeueReusableCellWithIdentifier:kOperationCellIdentifier];
+ switch (indexPath.row) {
+ case NTAdvertisingRow:
+ cell.textLabel.text = kAdvertisingOperationTitle;
+ self.advertisingSwitch = (UISwitch *)cell.accessoryView;
+ [self.advertisingSwitch addTarget:self
+ action:@selector(changeAdvertisingState:)
+ forControlEvents:UIControlEventValueChanged];
+ break;
+ case NTRangingRow:
+ default:
+ cell.textLabel.text = kRangingOperationTitle;
+ self.rangingSwitch = (UISwitch *)cell.accessoryView;
+ [self.rangingSwitch addTarget:self
+ action:@selector(changeRangingState:)
+ forControlEvents:UIControlEventValueChanged];
+ break;
+ }
+ }
+ break;
+ case NTDetectedBeaconsSection:
+ default: {
+ CLBeacon *beacon = self.detectedBeacons[indexPath.row];
+
+ cell = [tableView dequeueReusableCellWithIdentifier:kBeaconCellIdentifier];
+
+ if (!cell)
+ cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
+ reuseIdentifier:kBeaconCellIdentifier];
+
+ cell.textLabel.text = beacon.proximityUUID.UUIDString;
+ cell.detailTextLabel.text = [self detailsStringForBeacon:beacon];
+ cell.detailTextLabel.textColor = [UIColor grayColor];
+ }
+ break;
+ }
+
+ return cell;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
- return 1;
+ if (self.rangingSwitch.on) {
+ return kNumberOfSections; // All sections visible
+ } else {
+ return kNumberOfSections - 1; // Beacons section not visible
+ }
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
- return self.detectedBeacons.count;
+ switch (section) {
+ case NTOperationsSection:
+ return kNumberOfAvailableOperations;
+ case NTDetectedBeaconsSection:
+ default:
+ return self.detectedBeacons.count;
+ }
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
- return @"Detected beacons";
+ switch (section) {
+ case NTOperationsSection:
+ return nil;
+ case NTDetectedBeaconsSection:
+ default:
+ return kBeaconSectionTitle;
+ }
+}
+
+- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
+{
+ switch (indexPath.section) {
+ case NTOperationsSection:
+ return kOperationCellHeight;
+ case NTDetectedBeaconsSection:
+ default:
+ return kBeaconCellHeight;
+ }
+}
+
+- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
+{
+ UITableViewHeaderFooterView *headerView =
+ [[UITableViewHeaderFooterView alloc] initWithReuseIdentifier:kBeaconsHeaderViewIdentifier];
+
+ // Adds an activity indicator view to the section header
+ UIActivityIndicatorView *indicatorView =
+ [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
+ [headerView addSubview:indicatorView];
+
+ indicatorView.frame = (CGRect){kActivityIndicatorPosition, indicatorView.frame.size};
+
+ [indicatorView startAnimating];
+
+ return headerView;
}
@end
diff --git a/HiBeacons/main.m b/HiBeacons/main.m
index 07a55b3..67d24c9 100644
--- a/HiBeacons/main.m
+++ b/HiBeacons/main.m
@@ -6,8 +6,6 @@
// Copyright (c) 2013 Nick Toumpelis. All rights reserved.
//
-#import <UIKit/UIKit.h>
-
#import "NTHiBeaconsDelegate.h"
int main(int argc, char * argv[])
diff --git a/screenshot.png b/screenshot.png
index 81a73f2..f328365 100644
--- a/screenshot.png
+++ b/screenshot.png
Binary files differ