diff --git a/BCLRemoteApp.xcodeproj/project.pbxproj b/BCLRemoteApp.xcodeproj/project.pbxproj index 9ec3e1b..b00c291 100644 --- a/BCLRemoteApp.xcodeproj/project.pbxproj +++ b/BCLRemoteApp.xcodeproj/project.pbxproj @@ -42,6 +42,7 @@ AF6E0DB91B4D580100E07918 /* SystemSettingsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = AF6E0DB81B4D580100E07918 /* SystemSettingsViewController.xib */; }; AF6E0DBC1B4D584300E07918 /* BCLSystemSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = AF6E0DBB1B4D584300E07918 /* BCLSystemSettingsViewController.m */; }; AF7B68381B4BFED9004027D7 /* BCLTriggerTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = AF7B68371B4BFED9004027D7 /* BCLTriggerTableViewCell.m */; }; + BA4D1AD51DDE487200FA295D /* BCLAnnotation.m in Sources */ = {isa = PBXBuildFile; fileRef = BA4D1AD41DDE487200FA295D /* BCLAnnotation.m */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -108,6 +109,8 @@ AF7A1A4E1AF7ACAD0091DFF7 /* BCLRemoteApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BCLRemoteApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; AF7B68361B4BFED9004027D7 /* BCLTriggerTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BCLTriggerTableViewCell.h; path = BCLRemoteApp/Main/BCLTriggerTableViewCell.h; sourceTree = SOURCE_ROOT; }; AF7B68371B4BFED9004027D7 /* BCLTriggerTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BCLTriggerTableViewCell.m; path = BCLRemoteApp/Main/BCLTriggerTableViewCell.m; sourceTree = SOURCE_ROOT; }; + BA4D1AD31DDE487200FA295D /* BCLAnnotation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BCLAnnotation.h; path = BCLRemoteApp/Main/BCLAnnotation.h; sourceTree = SOURCE_ROOT; }; + BA4D1AD41DDE487200FA295D /* BCLAnnotation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BCLAnnotation.m; path = BCLRemoteApp/Main/BCLAnnotation.m; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -267,6 +270,8 @@ AF5A40B71BC2EB470044C486 /* BCLVendorChoiceViewController.m */, AF5A40B91BC2FC5A0044C486 /* BCLVendorCell.h */, AF5A40BA1BC2FC5A0044C486 /* BCLVendorCell.m */, + BA4D1AD31DDE487200FA295D /* BCLAnnotation.h */, + BA4D1AD41DDE487200FA295D /* BCLAnnotation.m */, ); name = Main; sourceTree = ""; @@ -296,12 +301,12 @@ isa = PBXNativeTarget; buildConfigurationList = AF7A1A741AF7ACAD0091DFF7 /* Build configuration list for PBXNativeTarget "BCLRemoteApp" */; buildPhases = ( - A4167EA327499F3735B077DF /* Check Pods Manifest.lock */, + A4167EA327499F3735B077DF /* [CP] Check Pods Manifest.lock */, AF7A1A4A1AF7ACAD0091DFF7 /* Sources */, AF7A1A4B1AF7ACAD0091DFF7 /* Frameworks */, AF7A1A4C1AF7ACAD0091DFF7 /* Resources */, - 030E5AAB9789D09E3D9A2C5F /* Copy Pods Resources */, - 3B51988D0E0BDDE4D3538BF8 /* Embed Pods Frameworks */, + 030E5AAB9789D09E3D9A2C5F /* [CP] Copy Pods Resources */, + 3B51988D0E0BDDE4D3538BF8 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -324,7 +329,7 @@ TargetAttributes = { AF7A1A4D1AF7ACAD0091DFF7 = { CreatedOnToolsVersion = 6.3.1; - DevelopmentTeam = 8TQGM4U3PU; + DevelopmentTeam = WWKF65T5X4; SystemCapabilities = { com.apple.BackgroundModes = { enabled = 1; @@ -373,14 +378,14 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 030E5AAB9789D09E3D9A2C5F /* Copy Pods Resources */ = { + 030E5AAB9789D09E3D9A2C5F /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "Copy Pods Resources"; + name = "[CP] Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; @@ -388,14 +393,14 @@ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-BCLRemoteApp/Pods-BCLRemoteApp-resources.sh\"\n"; showEnvVarsInLog = 0; }; - 3B51988D0E0BDDE4D3538BF8 /* Embed Pods Frameworks */ = { + 3B51988D0E0BDDE4D3538BF8 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "Embed Pods Frameworks"; + name = "[CP] Embed Pods Frameworks"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; @@ -403,14 +408,14 @@ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-BCLRemoteApp/Pods-BCLRemoteApp-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - A4167EA327499F3735B077DF /* Check Pods Manifest.lock */ = { + A4167EA327499F3735B077DF /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "Check Pods Manifest.lock"; + name = "[CP] Check Pods Manifest.lock"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; @@ -443,6 +448,7 @@ 7503CD091B445E1A00949512 /* BCLLoginViewController.m in Sources */, 7503CCFD1B445D9A00949512 /* BCLNotificationSetupViewController.m in Sources */, 7503CCEF1B445D4400949512 /* BLCZonesViewController.m in Sources */, + BA4D1AD51DDE487200FA295D /* BCLAnnotation.m in Sources */, 7503CCFC1B445D9A00949512 /* BCLMapViewController.m in Sources */, 7503CD081B445E1A00949512 /* BCLContainerViewController.m in Sources */, AF6E0DBC1B4D584300E07918 /* BCLSystemSettingsViewController.m in Sources */, @@ -550,7 +556,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.upnext.beaconctrl; PRODUCT_NAME = BCLRemoteApp; - PROVISIONING_PROFILE = ""; + PROVISIONING_PROFILE = "d07fdb34-def5-40b2-84e9-e2ce2bcc46d1"; }; name = Debug; }; @@ -567,7 +573,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.upnext.beaconctrl; PRODUCT_NAME = BCLRemoteApp; - PROVISIONING_PROFILE = "c72e83d0-15fc-487e-b9c1-f0c842337a97"; + PROVISIONING_PROFILE = "d07fdb34-def5-40b2-84e9-e2ce2bcc46d1"; }; name = Release; }; diff --git a/BCLRemoteApp/AppDelegate.m b/BCLRemoteApp/AppDelegate.m index 5eb1f1e..1979c54 100644 --- a/BCLRemoteApp/AppDelegate.m +++ b/BCLRemoteApp/AppDelegate.m @@ -12,7 +12,6 @@ #import "AppDelegate.h" #import #import "BeaconCtrlManager.h" -#import "RMConfiguration.h" #import "BCLSystemSettingsViewController.h" #import @@ -28,8 +27,6 @@ @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. - [[RMConfiguration sharedInstance] setAccessToken:@"pk.eyJ1IjoiYWNob2puYWNraSIsImEiOiJBNjFIdV8wIn0.Jm8FTlRfSHys8Og29_9WLg"]; - UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIRemoteNotificationTypeBadge |UIRemoteNotificationTypeSound |UIRemoteNotificationTypeAlert) categories:nil]; diff --git a/BCLRemoteApp/Info.plist b/BCLRemoteApp/Info.plist index 29cabe2..eeea2f0 100644 --- a/BCLRemoteApp/Info.plist +++ b/BCLRemoteApp/Info.plist @@ -2,6 +2,8 @@ + MGLMapboxAccessToken + pk.eyJ1IjoiYWNob2puYWNraSIsImEiOiJBNjFIdV8wIn0.Jm8FTlRfSHys8Og29_9WLg CFBundleDevelopmentRegion en CFBundleDisplayName diff --git a/BCLRemoteApp/Main/BCLAnnotation.h b/BCLRemoteApp/Main/BCLAnnotation.h new file mode 100644 index 0000000..50b0478 --- /dev/null +++ b/BCLRemoteApp/Main/BCLAnnotation.h @@ -0,0 +1,19 @@ +// +// BCLAnnotation.h +// BCLRemoteApp +// +// Created by minh on 17/11/16. +// Copyright © 2016 UpNext. All rights reserved. +// + +#import +#import "BCLBeacon.h" +@import Mapbox; + +@interface BCLAnnotation : NSObject + +@property (nonatomic, assign) CLLocationCoordinate2D coordinate; +@property (nonatomic, strong, nullable) BCLBeacon* userInfo; +@property (nonatomic, copy, nonnull) NSString *reuseIdentifier; + +@end diff --git a/BCLRemoteApp/Main/BCLAnnotation.m b/BCLRemoteApp/Main/BCLAnnotation.m new file mode 100644 index 0000000..84e76c8 --- /dev/null +++ b/BCLRemoteApp/Main/BCLAnnotation.m @@ -0,0 +1,13 @@ +// +// BCLAnnotation.m +// BCLRemoteApp +// +// Created by minh on 17/11/16. +// Copyright © 2016 UpNext. All rights reserved. +// + +#import "BCLAnnotation.h" + +@implementation BCLAnnotation + +@end diff --git a/BCLRemoteApp/Main/BCLMapViewController.m b/BCLRemoteApp/Main/BCLMapViewController.m index 469befe..707be56 100644 --- a/BCLRemoteApp/Main/BCLMapViewController.m +++ b/BCLRemoteApp/Main/BCLMapViewController.m @@ -18,9 +18,13 @@ #import "UIViewController+BCLActivityIndicator.h" #import "UIViewController+MFSideMenuAdditions.h" #import "AppDelegate.h" -#import +#import "BCLAnnotation.h" + #import +@import Mapbox; + + typedef NS_ENUM(NSUInteger, BCLMapViewControllerState) { kBCLMapViewControllerStateNormal, kBCLMapViewControllerStateBeaconSelected, @@ -35,50 +39,46 @@ typedef NS_ENUM(NSUInteger, BCLMapViewControllerState) { static CGFloat kBCLExtendedBeaconDetailsViewHeight = 169.0; static CGFloat kBCLHiddenBeaconDetailsViewHeight = 63.0; -@interface BCLMapViewController () -@property (weak, nonatomic) IBOutlet RMMapView *mapView; -@property (weak, nonatomic) IBOutlet UIImageView *pinView; -@property (weak, nonatomic) IBOutlet UIButton *addButton; -@property (weak, nonatomic) IBOutlet UIButton *moveButton; -@property (weak, nonatomic) IBOutlet NSLayoutConstraint *beaconDetailsConstraint; -@property (weak, nonatomic) IBOutlet UIView *containerView; -@property (weak, nonatomic) IBOutlet NSLayoutConstraint *buttonsDistanceConstraint; +@interface BCLMapViewController () +@property(strong) IBOutlet MGLMapView *mapView; +@property(weak, nonatomic) IBOutlet UIView *mapViewContainer; +@property(weak, nonatomic) IBOutlet UIImageView *pinView; +@property(weak, nonatomic) IBOutlet UIButton *addButton; +@property(weak, nonatomic) IBOutlet UIButton *moveButton; +@property(weak, nonatomic) IBOutlet NSLayoutConstraint *beaconDetailsConstraint; +@property(weak, nonatomic) IBOutlet UIView *containerView; +@property(weak, nonatomic) IBOutlet NSLayoutConstraint *buttonsDistanceConstraint; -@property (strong, nonatomic) BCLBeaconDetailsViewController *beaconDetailsViewController; -@property (nonatomic) BCLMapViewControllerState state; +@property(strong, nonatomic) BCLBeaconDetailsViewController *beaconDetailsViewController; +@property(nonatomic) BCLMapViewControllerState state; -@property (strong, nonatomic) NSSet *beacons; +@property(strong, nonatomic) NSSet *beacons; -@property (nonatomic, strong) BCLBeacon *currentlyAddedBeacon; -@property (nonatomic, strong) BCLBeacon *currentlyEditedBeacon; -@property (nonatomic, strong) BeaconCtrlManager *beaconCtrlManager; +@property(nonatomic, strong) BCLBeacon *currentlyAddedBeacon; +@property(nonatomic, strong) BCLBeacon *currentlyEditedBeacon; +@property(nonatomic, strong) BeaconCtrlManager *beaconCtrlManager; -@property (nonatomic, strong) NSArray *filteredZones; -@property (nonatomic) BOOL showsNoneZone; -@property (nonatomic) NSNumber *floor; +@property(nonatomic, strong) NSArray *filteredZones; +@property(nonatomic) BOOL showsNoneZone; +@property(nonatomic) NSNumber *floor; @property(nonatomic) BOOL needsReload; @property(nonatomic) BOOL didVerifySystemSettings; @end @implementation BCLMapViewController -- (void)dealloc -{ +- (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; } #pragma mark - UIViewController -- (void)viewDidLoad -{ +- (void)viewDidLoad { [super viewDidLoad]; - // map view configuration - RMMapboxSource *tileSource = [[RMMapboxSource alloc] initWithMapID:@"achojnacki.941d2079"]; - [self.mapView addTileSource:tileSource]; - self.mapView.showsUserLocation = YES; - self.mapView.userTrackingMode = RMUserTrackingModeFollow; self.mapView.delegate = self; + self.mapView.showsUserLocation = YES; + self.mapView.userTrackingMode = MGLUserTrackingModeFollow; //initial views setup self.state = kBCLMapViewControllerStateNormal; @@ -91,7 +91,7 @@ - (void)viewDidLoad layer.shadowOpacity = 0.3; layer.shadowRadius = 5.0; - self.mapView.zoom = 18; + self.mapView.zoomLevel = 0; self.showsNoneZone = YES; self.floor = nil; @@ -99,8 +99,7 @@ - (void)viewDidLoad [self reloadBeacons]; } -- (void)viewDidAppear:(BOOL)animated -{ +- (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; if (!self.didVerifySystemSettings) { AppDelegate *delegate = [UIApplication sharedApplication].delegate; @@ -109,8 +108,7 @@ - (void)viewDidAppear:(BOOL)animated } } -- (void)setNeedsReload -{ +- (void)setNeedsReload { __weak BCLMapViewController *weakSelf = self; dispatch_async(dispatch_get_main_queue(), ^{ if (weakSelf.state == kBCLMapViewControllerStateNormal) { @@ -121,8 +119,7 @@ - (void)setNeedsReload }); } -- (void)reloadConfiguration -{ +- (void)reloadConfiguration { if (self.filteredZones) { NSMutableArray *newFilteredZones = [NSMutableArray new]; for (BCLZone *zone in [BeaconCtrlManager sharedManager].beaconCtrl.configuration.zones) { @@ -138,25 +135,24 @@ - (void)reloadConfiguration [self reloadBeacons]; } -- (void)viewWillAppear:(BOOL)animated -{ +- (void)viewWillAppear:(BOOL)animated { self.menuContainerViewController.panMode = MFSideMenuPanModeDefault; } -- (void)viewWillDisappear:(BOOL)animated -{ +- (void)viewWillDisappear:(BOOL)animated { self.menuContainerViewController.panMode = MFSideMenuPanModeNone; } -- (UIStatusBarStyle)preferredStatusBarStyle -{ +- (UIStatusBarStyle)preferredStatusBarStyle { return UIStatusBarStyleDefault; } -- (RMAnnotation *)addAnnotationForBeacon:(BCLBeacon *)beacon -{ - RMAnnotation *annotation = [RMAnnotation annotationWithMapView:self.mapView coordinate:beacon.location.location.coordinate andTitle:nil]; +- (BCLAnnotation *)addAnnotationForBeacon:(BCLBeacon *)beacon { + + BCLAnnotation *annotation = [BCLAnnotation new]; + annotation.reuseIdentifier = [NSString stringWithFormat:@"annotationWithBeaconId_%@", beacon.instanceId]; + annotation.coordinate = beacon.location.location.coordinate; annotation.userInfo = beacon; [self.mapView addAnnotation:annotation]; @@ -165,39 +161,37 @@ - (RMAnnotation *)addAnnotationForBeacon:(BCLBeacon *)beacon #pragma mark - Private -- (void)clearBeacons -{ - [self.mapView removeAllAnnotations]; +- (void)clearBeacons { + [self.mapView removeAnnotations:self.mapView.annotations]; } -- (void)reloadBeacons -{ +- (void)reloadBeacons { self.needsReload = NO; __weak BCLMapViewController *weakSelf = self; [self setState:kBCLMapViewControllerStateNormal animated:NO completion:^(BOOL finished) { [weakSelf clearBeacons]; - weakSelf.beacons = self.beaconCtrlManager.beaconCtrl.configuration.beacons; - if (!self.filteredZones) { - for (BCLBeacon *beacon in self.beacons) { - if ([self beaconsOnCurrentFloor:beacon] && (self.showsNoneZone || beacon.zone)) { - RMAnnotation *annotation = [self addAnnotationForBeacon:beacon]; - [self selectAnnotationIfNecessary:annotation]; + weakSelf.beacons = weakSelf.beaconCtrlManager.beaconCtrl.configuration.beacons; + if (!weakSelf.filteredZones) { + for (BCLBeacon *beacon in weakSelf.beacons) { + if ([weakSelf beaconsOnCurrentFloor:beacon] && (weakSelf.showsNoneZone || beacon.zone)) { + BCLAnnotation *annotation = [weakSelf addAnnotationForBeacon:beacon]; + [weakSelf selectAnnotationIfNecessary:annotation]; } } } else { - for (BCLZone *zone in self.filteredZones) { + for (BCLZone *zone in weakSelf.filteredZones) { for (BCLBeacon *beacon in zone.beacons) { - if ([self beaconsOnCurrentFloor:beacon]) { - RMAnnotation *annotation = [self addAnnotationForBeacon:beacon]; - [self selectAnnotationIfNecessary:annotation]; + if ([weakSelf beaconsOnCurrentFloor:beacon]) { + BCLAnnotation *annotation = [weakSelf addAnnotationForBeacon:beacon]; + [weakSelf selectAnnotationIfNecessary:annotation]; } } } - if (self.showsNoneZone) { - for (BCLBeacon * beacon in self.beacons) { - if (!beacon.zone && [self beaconsOnCurrentFloor:beacon]) { - RMAnnotation *annotation = [self addAnnotationForBeacon:beacon]; - [self selectAnnotationIfNecessary:annotation]; + if (weakSelf.showsNoneZone) { + for (BCLBeacon *beacon in weakSelf.beacons) { + if (!beacon.zone && [weakSelf beaconsOnCurrentFloor:beacon]) { + BCLAnnotation *annotation = [weakSelf addAnnotationForBeacon:beacon]; + [weakSelf selectAnnotationIfNecessary:annotation]; } } } @@ -205,34 +199,30 @@ - (void)reloadBeacons }]; } -- (void)selectAnnotationIfNecessary:(RMAnnotation *)annotation -{ +- (void)selectAnnotationIfNecessary:(BCLAnnotation *)annotation { BCLBeacon *beacon = annotation.userInfo; if ([beacon.beaconIdentifier isEqualToString:self.currentlyEditedBeacon.beaconIdentifier]) { [self.mapView selectAnnotation:annotation animated:NO]; } } -- (BOOL)beaconsOnCurrentFloor:(BCLBeacon *)beacon -{ +- (BOOL)beaconsOnCurrentFloor:(BCLBeacon *)beacon { if (!self.floor) { return YES; } - + if ([self.floor isEqualToNumber:@(NSNotFound)]) { return beacon.location.floor == nil; } - + return [beacon.location.floor isEqualToNumber:self.floor]; } -- (void)centerCurrentlySelectedAnnotationAnimated:(BOOL)animated -{ - CGPoint pinPoint = [self.mapView convertPoint:self.pinView.center fromView:self.view]; - CLLocationCoordinate2D coordinate2D = [self.mapView pixelToCoordinate:pinPoint]; +- (void)centerCurrentlySelectedAnnotationAnimated:(BOOL)animated { + CLLocationCoordinate2D coordinate2D = [self.mapView convertPoint:self.pinView.center toCoordinateFromView:self.view]; CLLocationDegrees latDelta = coordinate2D.latitude - self.mapView.centerCoordinate.latitude; - CLLocationCoordinate2D centerCoordinate = self.mapView.selectedAnnotation.coordinate; + CLLocationCoordinate2D centerCoordinate = self.mapView.selectedAnnotations[0].coordinate; centerCoordinate.latitude = centerCoordinate.latitude - latDelta; //don't do anything if mapview already centered @@ -254,13 +244,13 @@ - (IBAction)moveButtonPressed:(id)sender { __weak BCLMapViewController *weakSelf = self; switch (self.state) { - case kBCLMapViewControllerStateNormal:break; + case kBCLMapViewControllerStateNormal: + break; - case kBCLMapViewControllerStateBeaconSelected: - { + case kBCLMapViewControllerStateBeaconSelected: { [self centerCurrentlySelectedAnnotationAnimated:NO]; [self setState:kBCLMapViewControllerStateNewBeacon animated:NO completion:^(BOOL finished) { - [weakSelf.mapView removeAnnotation:weakSelf.mapView.selectedAnnotation]; + [weakSelf.mapView removeAnnotation:weakSelf.mapView.selectedAnnotations[0]]; }]; }; break; @@ -273,30 +263,27 @@ - (IBAction)moveButtonPressed:(id)sender { [self setState:kBCLMapViewControllerStateNormal animated:YES]; } break; - case kBCLMapViewControllerStateShowsBeaconDetails:break; + case kBCLMapViewControllerStateShowsBeaconDetails: + break; } } -- (IBAction)addButtonPressed:(id)sender -{ +- (IBAction)addButtonPressed:(id)sender { switch (self.state) { - case kBCLMapViewControllerStateNormal: - { + case kBCLMapViewControllerStateNormal: { [self setState:kBCLMapViewControllerStateNewBeacon animated:YES]; } break; - case kBCLMapViewControllerStateBeaconSelected: - { + case kBCLMapViewControllerStateBeaconSelected: { [self.navigationController pushViewController:self.beaconDetailsViewController animated:YES]; }; break; - case kBCLMapViewControllerStateNewBeacon: - { + case kBCLMapViewControllerStateNewBeacon: { CGPoint pinPoint = [self.mapView convertPoint:self.pinView.center fromView:self.view]; - CLLocationCoordinate2D coordinate2D = [self.mapView pixelToCoordinate:pinPoint]; + CLLocationCoordinate2D coordinate2D = [self.mapView convertPoint:pinPoint toCoordinateFromView:self.mapView]; CLLocation *location = [[CLLocation alloc] initWithLatitude:coordinate2D.latitude longitude:coordinate2D.longitude]; if (self.currentlyEditedBeacon) { @@ -311,7 +298,7 @@ - (IBAction)addButtonPressed:(id)sender [weakSelf hideActivityIndicatorViewAnimated:YES]; if (!error) { weakSelf.currentlyEditedBeacon = updatedBeacon; - RMAnnotation *annotation = weakSelf.mapView.selectedAnnotation; + BCLAnnotation *annotation = weakSelf.mapView.selectedAnnotations[0]; annotation.coordinate = updatedBeacon.location.location.coordinate; annotation.userInfo = updatedBeacon; [self setState:kBCLMapViewControllerStateBeaconSelected animated:YES]; @@ -337,8 +324,7 @@ - (IBAction)addButtonPressed:(id)sender } break; - case kBCLMapViewControllerStateShowsBeaconDetails: - { + case kBCLMapViewControllerStateShowsBeaconDetails: { }; break; @@ -347,208 +333,211 @@ - (IBAction)addButtonPressed:(id)sender #pragma mark - Accessors -- (void)setState:(enum BCLMapViewControllerState)state animated:(BOOL)animated completion:(void(^)(BOOL))completion -{ +- (void)setState:(enum BCLMapViewControllerState)state animated:(BOOL)animated completion:(void (^)(BOOL))completion { _state = state; - [UIView animateWithDuration:animated?kBCLTransitionDuration:0.0 + [UIView animateWithDuration:animated ? kBCLTransitionDuration : 0.0 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{ - switch (state) { - case kBCLMapViewControllerStateNormal: - { - self.beaconDetailsConstraint.constant = kBCLHiddenBeaconDetailsViewHeight; - [self.addButton setImage:[UIImage imageNamed:@"plus_mapbtn"] forState:UIControlStateNormal]; - self.addButton.transform = CGAffineTransformIdentity; - self.pinView.hidden = YES; - self.buttonsDistanceConstraint.constant = 0.0; - }; - break; - case kBCLMapViewControllerStateBeaconSelected: - { - [self.beaconCtrlManager muteAutomaticBeaconCtrlConfigurationRefresh]; - if (!self.pinView.hidden && self.currentlyEditedBeacon) { - [self.mapView addAnnotation:self.mapView.selectedAnnotation]; - } - - self.beaconDetailsConstraint.constant = kBCLExtendedBeaconDetailsViewHeight; - [self.addButton setImage:[UIImage imageNamed:@"settings_mapbtn"] forState:UIControlStateNormal]; - [self.moveButton setImage:[UIImage imageNamed:@"move_mapbtn"] forState:UIControlStateNormal]; - self.addButton.transform = CGAffineTransformIdentity; - self.pinView.hidden = YES; - self.buttonsDistanceConstraint.constant = 65.0; - - //center & select annotation - RMAnnotation *annotation = self.mapView.selectedAnnotation; - self.currentlyEditedBeacon = (BCLBeacon *)annotation.userInfo;; - [self centerCurrentlySelectedAnnotationAnimated:YES]; - BCLBeacon *beacon = annotation.userInfo; - if (beacon.zone) { - annotation.layer = [[RMMarker alloc] initWithUIImage:[UIImage beaconMarkerWithColor:beacon.zone.color highlighted:YES needsUpdate:beacon.needsCharacteristicsUpdate || beacon.needsFirmwareUpdate]]; - } else { - annotation.layer = [[RMMarker alloc] initWithUIImage:[UIImage imageNamed:@"beaconWithoutZonePressed"]]; + switch (state) { + case kBCLMapViewControllerStateNormal: { + self.beaconDetailsConstraint.constant = kBCLHiddenBeaconDetailsViewHeight; + [self.addButton setImage:[UIImage imageNamed:@"plus_mapbtn"] forState:UIControlStateNormal]; + self.addButton.transform = CGAffineTransformIdentity; + self.pinView.hidden = YES; + self.buttonsDistanceConstraint.constant = 0.0; + }; + break; + case kBCLMapViewControllerStateBeaconSelected: { + [self.beaconCtrlManager muteAutomaticBeaconCtrlConfigurationRefresh]; + if (!self.pinView.hidden && self.currentlyEditedBeacon) { + [self.mapView addAnnotation:self.mapView.selectedAnnotations[0]]; + } + + self.beaconDetailsConstraint.constant = kBCLExtendedBeaconDetailsViewHeight; + [self.addButton setImage:[UIImage imageNamed:@"settings_mapbtn"] forState:UIControlStateNormal]; + [self.moveButton setImage:[UIImage imageNamed:@"move_mapbtn"] forState:UIControlStateNormal]; + self.addButton.transform = CGAffineTransformIdentity; + self.pinView.hidden = YES; + self.buttonsDistanceConstraint.constant = 65.0; + + //center & select annotation + BCLAnnotation *annotation = self.mapView.selectedAnnotations[0]; + BCLBeacon *beacon = annotation.userInfo; + + self.currentlyEditedBeacon = (BCLBeacon *) annotation.userInfo;; + [self centerCurrentlySelectedAnnotationAnimated:YES]; + + UIImage *image; + if (beacon.zone) { + image = [UIImage beaconMarkerWithColor:beacon.zone.color highlighted:YES needsUpdate:beacon.needsCharacteristicsUpdate || beacon.needsFirmwareUpdate]; + } else { + image = [UIImage imageNamed:@"beaconWithoutZonePressed"]; + } + MGLAnnotationImage *annotationImage = [self.mapView dequeueReusableAnnotationImageWithIdentifier:annotation.reuseIdentifier]; + annotationImage.image = image; + }; + break; + case kBCLMapViewControllerStateNewBeacon: { + [self.beaconCtrlManager muteAutomaticBeaconCtrlConfigurationRefresh]; + if (self.currentlyEditedBeacon) { + [self.addButton setImage:[UIImage imageNamed:@"ok_mapbtn"] forState:UIControlStateNormal]; + } else { + [self.addButton setImage:[UIImage imageNamed:@"arrow_mapbtn"] forState:UIControlStateNormal]; + } + [self.moveButton setImage:[UIImage imageNamed:@"cancel_mapbtn"] forState:UIControlStateNormal]; + self.beaconDetailsConstraint.constant = kBCLExtendedBeaconDetailsViewHeight; + self.addButton.transform = CGAffineTransformIdentity; + self.buttonsDistanceConstraint.constant = 65.0; + }; + break; + case kBCLMapViewControllerStateShowsBeaconDetails: { + [self.beaconCtrlManager muteAutomaticBeaconCtrlConfigurationRefresh]; + self.beaconDetailsConstraint.constant = self.view.bounds.size.height; + self.addButton.transform = CGAffineTransformMakeRotation(3 * M_PI_2); + self.buttonsDistanceConstraint.constant = 0.0; + }; + break; + } + + [self.view layoutIfNeeded]; + } completion:^(BOOL finished) { + //check if state wasn't changed before animation completion + if (state == _state && finished) { + switch (state) { + case kBCLMapViewControllerStateNormal: + [self.beaconCtrlManager unmuteAutomaticBeaconCtrlConfigurationRefresh]; + self.currentlyAddedBeacon = nil; + self.currentlyEditedBeacon = nil; + self.beaconDetailsViewController.view.userInteractionEnabled = NO; + self.beaconDetailsViewController.beaconMode = kBCLBeaconModeHidden; + if (self.needsReload) { + [self reloadConfiguration]; + } + break; + case kBCLMapViewControllerStateBeaconSelected: + self.beaconDetailsViewController.view.userInteractionEnabled = NO; + self.beaconDetailsViewController.beaconMode = kBCLBeaconModeDetails; + break; + case kBCLMapViewControllerStateNewBeacon: + self.beaconDetailsViewController.view.userInteractionEnabled = NO; + self.pinView.hidden = NO; + self.beaconDetailsViewController.beaconMode = kBCLBeaconModeNew; + break; + case kBCLMapViewControllerStateShowsBeaconDetails: + self.beaconDetailsViewController.view.userInteractionEnabled = YES; + break; + } } - }; - break; - case kBCLMapViewControllerStateNewBeacon: - { - [self.beaconCtrlManager muteAutomaticBeaconCtrlConfigurationRefresh]; - if (self.currentlyEditedBeacon) { - [self.addButton setImage:[UIImage imageNamed:@"ok_mapbtn"] forState:UIControlStateNormal]; - } else { - [self.addButton setImage:[UIImage imageNamed:@"arrow_mapbtn"] forState:UIControlStateNormal]; + if (completion) { + completion(finished); } - [self.moveButton setImage:[UIImage imageNamed:@"cancel_mapbtn"] forState:UIControlStateNormal]; - self.beaconDetailsConstraint.constant = kBCLExtendedBeaconDetailsViewHeight; - self.addButton.transform = CGAffineTransformIdentity; - self.buttonsDistanceConstraint.constant = 65.0; - }; - break; - case kBCLMapViewControllerStateShowsBeaconDetails: { - [self.beaconCtrlManager muteAutomaticBeaconCtrlConfigurationRefresh]; - self.beaconDetailsConstraint.constant = self.view.bounds.size.height; - self.addButton.transform = CGAffineTransformMakeRotation(3*M_PI_2); - self.buttonsDistanceConstraint.constant = 0.0; - }; - break; - } - - [self.view layoutIfNeeded]; - } completion:^(BOOL finished){ - //check if state wasn't changed before animation completion - if (state == _state && finished) { - switch (state) { - case kBCLMapViewControllerStateNormal: - [self.beaconCtrlManager unmuteAutomaticBeaconCtrlConfigurationRefresh]; - self.currentlyAddedBeacon = nil; - self.currentlyEditedBeacon = nil; - self.beaconDetailsViewController.view.userInteractionEnabled = NO; - self.beaconDetailsViewController.beaconMode = kBCLBeaconModeHidden; - if (self.needsReload) { - [self reloadConfiguration]; - } - break; - case kBCLMapViewControllerStateBeaconSelected: - self.beaconDetailsViewController.view.userInteractionEnabled = NO; - self.beaconDetailsViewController.beaconMode = kBCLBeaconModeDetails; - break; - case kBCLMapViewControllerStateNewBeacon: - self.beaconDetailsViewController.view.userInteractionEnabled = NO; - self.pinView.hidden = NO; - self.beaconDetailsViewController.beaconMode = kBCLBeaconModeNew; - break; - case kBCLMapViewControllerStateShowsBeaconDetails: - self.beaconDetailsViewController.view.userInteractionEnabled = YES; - break; - } - } - if (completion) { - completion(finished); - } - }]; + }]; } -- (void)setState:(BCLMapViewControllerState)state animated:(BOOL)animated -{ +- (void)setState:(BCLMapViewControllerState)state animated:(BOOL)animated { [self setState:state animated:animated completion:nil]; } -- (void)setState:(BCLMapViewControllerState)state -{ +- (void)setState:(BCLMapViewControllerState)state { [self setState:state animated:NO]; } -- (void)setCurrentlyAddedBeacon:(BCLBeacon *)currentlyAddedBeacon -{ +- (void)setCurrentlyAddedBeacon:(BCLBeacon *)currentlyAddedBeacon { _currentlyAddedBeacon = currentlyAddedBeacon; _currentlyEditedBeacon = nil; self.beaconDetailsViewController.beacon = currentlyAddedBeacon; self.beaconDetailsViewController.beaconMode = kBCLBeaconModeNew; } -- (void)setCurrentlyEditedBeacon:(BCLBeacon *)currentlyEditedBeacon -{ +- (void)setCurrentlyEditedBeacon:(BCLBeacon *)currentlyEditedBeacon { _currentlyEditedBeacon = currentlyEditedBeacon; _currentlyAddedBeacon = nil; self.beaconDetailsViewController.beacon = currentlyEditedBeacon; self.beaconDetailsViewController.beaconMode = kBCLBeaconModeDetails; } -- (BeaconCtrlManager *)beaconCtrlManager -{ +- (BeaconCtrlManager *)beaconCtrlManager { return [BeaconCtrlManager sharedManager]; } #pragma mark Side Menu Delegate -- (void)sideMenuViewController:(BCLSideMenuViewController *)controller didChangeSelection:(NSArray *)selection showsNoneZone:(BOOL)showsNone -{ +- (void)sideMenuViewController:(BCLSideMenuViewController *)controller didChangeSelection:(NSArray *)selection showsNoneZone:(BOOL)showsNone { self.filteredZones = selection; self.showsNoneZone = showsNone; [self reloadBeacons]; } -- (void)sideMenuViewController:(BCLSideMenuViewController *)controller didSelectFloorNumber:(NSNumber *)floorNumber -{ +- (void)sideMenuViewController:(BCLSideMenuViewController *)controller didSelectFloorNumber:(NSNumber *)floorNumber { self.floor = floorNumber; [self reloadBeacons]; } #pragma mark MapView Delegate -- (RMMapLayer *)mapView:(RMMapView *)mapView layerForAnnotation:(RMAnnotation *)annotation -{ - if (annotation.isUserLocationAnnotation) +- (nullable MGLAnnotationImage *)mapView:(nonnull MGLMapView *)mapView imageForAnnotation:(nonnull id )annotation { + + if (![annotation isKindOfClass:[BCLAnnotation class]]) { return nil; + } - BCLBeacon *beacon = annotation.userInfo; - - RMMarker *marker; - if (annotation == mapView.selectedAnnotation) { - marker = [[RMMarker alloc] initWithUIImage:[UIImage beaconMarkerWithColor:[UIColor redColor] highlighted:NO needsUpdate:YES]]; + BCLAnnotation *bclAnnotation = (BCLAnnotation *) annotation; + BCLBeacon *beacon = bclAnnotation.userInfo; + + UIImage *image; + + if (mapView.selectedAnnotations.count > 0 && bclAnnotation == [mapView.selectedAnnotations objectAtIndex:0]) { + image = [UIImage beaconMarkerWithColor:[UIColor redColor] highlighted:NO needsUpdate:YES]; } else { if (beacon.zone.color) { - marker = [[RMMarker alloc] initWithUIImage:[UIImage beaconMarkerWithColor:beacon.zone.color highlighted:NO needsUpdate:beacon.needsCharacteristicsUpdate || beacon.needsFirmwareUpdate]]; + image = [UIImage beaconMarkerWithColor:beacon.zone.color highlighted:NO needsUpdate:beacon.needsCharacteristicsUpdate || beacon.needsFirmwareUpdate]; } else { - marker = [[RMMarker alloc] initWithUIImage:[UIImage imageNamed:beacon.needsFirmwareUpdate || beacon.needsCharacteristicsUpdate ? @"beaconWithoutZoneRed" : @"beaconWithoutZone"]]; + image = [UIImage imageNamed:beacon.needsFirmwareUpdate || beacon.needsCharacteristicsUpdate ? @"beaconWithoutZoneRed" : @"beaconWithoutZone"]; } } - return marker; + + return [MGLAnnotationImage annotationImageWithImage:image reuseIdentifier:bclAnnotation.reuseIdentifier]; } -- (void)mapView:(RMMapView *)mapView didSelectAnnotation:(RMAnnotation *)annotation -{ - if (![annotation isKindOfClass:[RMUserLocation class]]) { +- (void)mapView:(nonnull MGLMapView *)mapView didSelectAnnotation:(nonnull id )annotation { + if ([annotation isKindOfClass:[BCLAnnotation class]]) { [self setState:kBCLMapViewControllerStateBeaconSelected animated:YES]; } } -- (void)mapView:(RMMapView *)mapView didDeselectAnnotation:(RMAnnotation *)annotation -{ - if (![annotation isKindOfClass:[RMUserLocation class]]) { - BCLBeacon *beacon = annotation.userInfo; +- (void)mapView:(nonnull MGLMapView *)mapView didDeselectAnnotation:(nonnull id )annotation { + + if ([annotation isKindOfClass:[BCLAnnotation class]]) { + BCLAnnotation *bclAnnotation = (BCLAnnotation *) annotation; + BCLBeacon *beacon = bclAnnotation.userInfo; + UIImage *image; + if (beacon.zone.color) { - annotation.layer = [[RMMarker alloc] initWithUIImage:[UIImage beaconMarkerWithColor:beacon.zone.color highlighted:NO needsUpdate:beacon.needsCharacteristicsUpdate || beacon.needsFirmwareUpdate]]; + image = [UIImage beaconMarkerWithColor:beacon.zone.color highlighted:NO needsUpdate:beacon.needsCharacteristicsUpdate || beacon.needsFirmwareUpdate]; } else { - annotation.layer = [[RMMarker alloc] initWithUIImage:[UIImage imageNamed:beacon.needsFirmwareUpdate || beacon.needsFirmwareUpdate ? @"beaconWithoutZoneRed" : @"beaconWithoutZone"]]; + image = [UIImage imageNamed:beacon.needsCharacteristicsUpdate || beacon.needsFirmwareUpdate ? @"beaconWithoutZoneRed" : @"beaconWithoutZone"]; } if (self.state == kBCLMapViewControllerStateNewBeacon) { [self.mapView addAnnotation:annotation]; + } else { + MGLAnnotationImage *annotationImage = [self.mapView dequeueReusableAnnotationImageWithIdentifier:bclAnnotation.reuseIdentifier]; + annotationImage.image = image; + } [self setState:kBCLMapViewControllerStateNormal animated:YES]; } } - #pragma mark - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if ([segue.identifier isEqualToString:kBCLBeaconDetailsSegueIdentifier]) { BCLBeaconDetailsViewController *viewController = segue.destinationViewController; - viewController.beacon = (BCLBeacon *)sender; + viewController.beacon = (BCLBeacon *) sender; viewController.delegate = self; } else if ([segue.identifier isEqualToString:kBCLEmbedBeaconDetailsSegueIdentifier]) { self.beaconDetailsViewController = segue.destinationViewController; @@ -559,9 +548,8 @@ - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { #pragma mark - UINavigationController Delegate -- (id)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC -{ - if (([toVC isKindOfClass:[BCLBeaconDetailsViewController class]] && fromVC == self) || ([fromVC isKindOfClass:[BCLBeaconDetailsViewController class]] && toVC == self)){ +- (id )navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC { + if (([toVC isKindOfClass:[BCLBeaconDetailsViewController class]] && fromVC == self) || ([fromVC isKindOfClass:[BCLBeaconDetailsViewController class]] && toVC == self)) { return self; } return nil; @@ -569,21 +557,19 @@ - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { #pragma mark - Animated Transitioning -- (NSTimeInterval)transitionDuration:(id )transitionContext -{ +- (NSTimeInterval)transitionDuration:(id )transitionContext { return kBCLTransitionDuration; } -- (void)animateTransition:(id)transitionContext -{ +- (void)animateTransition:(id )transitionContext { __weak BCLMapViewController *weakSelf = self; //disable interactions during transition self.view.userInteractionEnabled = NO; - void(^completion)(BOOL finished) = ^(BOOL finished){ + void (^completion)(BOOL finished) = ^(BOOL finished) { weakSelf.view.userInteractionEnabled = YES; }; - UIViewController* toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; + UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; if ([toViewController isKindOfClass:[BCLBeaconDetailsViewController class]]) { [self setState:kBCLMapViewControllerStateShowsBeaconDetails animated:YES completion:^(BOOL finished) { [transitionContext completeTransition:![transitionContext transitionWasCancelled]]; @@ -609,31 +595,26 @@ - (void)animateTransition:(id)transitionCo #pragma mark - Beacon Details View Delegate -- (void)beaconDetailsViewController:(BCLBeaconDetailsViewController *)viewController didSaveNewBeacon:(BCLBeacon *)beacon -{ - //self.currentlyAddedBeacon = nil; - RMAnnotation *annotation = [RMAnnotation annotationWithMapView:self.mapView coordinate:beacon.location.location.coordinate andTitle:nil]; - annotation.userInfo = beacon; - [self.mapView addAnnotation:annotation]; - [self.mapView setSelectedAnnotation:annotation]; +- (void)beaconDetailsViewController:(BCLBeaconDetailsViewController *)viewController didSaveNewBeacon:(BCLBeacon *)beacon { + + BCLAnnotation *annotation = [self addAnnotationForBeacon:beacon]; + [self.mapView selectAnnotation:annotation animated:YES]; [self.navigationController popViewControllerAnimated:YES]; } -- (void)beaconDetailsViewController:(BCLBeaconDetailsViewController *)viewController didEditBeacon:(BCLBeacon *)beacon -{ - //self.currentlyEditedBeacon = nil; - RMAnnotation *annotation = self.mapView.selectedAnnotation; +- (void)beaconDetailsViewController:(BCLBeaconDetailsViewController *)viewController didEditBeacon:(BCLBeacon *)beacon { + BCLAnnotation *annotation = self.mapView.selectedAnnotations[0]; annotation.userInfo = beacon; annotation.coordinate = beacon.location.location.coordinate; + annotation.reuseIdentifier = [NSString stringWithFormat:@"annotationWithBeaconId_%@", beacon.instanceId]; [self.mapView addAnnotation:annotation]; - [self.mapView setSelectedAnnotation:annotation]; + [self.mapView selectAnnotation:annotation animated:YES]; [self.navigationController popViewControllerAnimated:YES]; } -- (void)beaconDetailsViewController:(BCLBeaconDetailsViewController *)controller didDeleteBeacon:(BCLBeacon *)beacon -{ +- (void)beaconDetailsViewController:(BCLBeaconDetailsViewController *)controller didDeleteBeacon:(BCLBeacon *)beacon { self.currentlyEditedBeacon = nil; - RMAnnotation *annotation = self.mapView.selectedAnnotation; + BCLAnnotation *annotation = self.mapView.selectedAnnotations[0]; [self.mapView removeAnnotation:annotation]; [self.mapView deselectAnnotation:annotation animated:NO]; [self.navigationController popViewControllerAnimated:YES]; diff --git a/BCLRemoteApp/Main/Main.storyboard b/BCLRemoteApp/Main/Main.storyboard index 2fc983b..8e5ea6f 100644 --- a/BCLRemoteApp/Main/Main.storyboard +++ b/BCLRemoteApp/Main/Main.storyboard @@ -1,12 +1,31 @@ - + - + + + + HelveticaNeue-Medium + HelveticaNeue-Bold + HelveticaNeue-Medium + HelveticaNeue-Bold + HelveticaNeue-Medium + HelveticaNeue-Bold + HelveticaNeue-Medium + HelveticaNeue-Bold + HelveticaNeue-Bold + HelveticaNeue-Medium + HelveticaNeue-Medium + HelveticaNeue-Bold + HelveticaNeue-Medium + HelveticaNeue-Bold + HelveticaNeue-Bold + + @@ -41,11 +60,11 @@ - + - @@ -302,7 +319,7 @@ @@ -326,7 +343,7 @@ @@ -414,7 +431,7 @@ @@ -460,7 +477,7 @@ @@ -491,7 +508,7 @@ -