Skip to content

Instantly share code, notes, and snippets.

@charleshkang
Created December 3, 2015 04:49
Show Gist options
  • Save charleshkang/2fecfdb1e359d4c16166 to your computer and use it in GitHub Desktop.
Save charleshkang/2fecfdb1e359d4c16166 to your computer and use it in GitHub Desktop.
//
// NLMapViewController.m
// neverlate
//
// Created by Charles Kang on 11/16/15.
// Copyright © 2015 Charles Kang. All rights reserved.
//
#import <Parse/Parse.h>
#import <Venmo-iOS-SDK/Venmo.h>
#import "NLMapView.h"
#import "NLUser.h"
#import "NLGoal.h"
#import "NSDate+NLLocalTime.h"
@implementation NLMapView
- (void)awakeFromNib {
[super awakeFromNib];
[self requestLocationPermission];
[self regionForSavedLocation];
// [self animateViewUp:YES];
// [self setupTapGestureRecognizer];
// set hasUserLocation to false
self.hasUserLocation = false;
// set delegates
self.locationManager.delegate = self;
[self.locationManager startUpdatingLocation];
self.searchTextField.delegate = self;
CLLocationDegrees lat = [[self.geofence valueForKey:@"NeverLateGoalLocations"] doubleValue];
CLLocationDegrees lon = [[self.geofence valueForKey:@"NeverLateGoalLocations"] doubleValue];
CLLocationDistance radius = [[self.geofence valueForKey:@"radius"] doubleValue];
CLLocationCoordinate2D center = CLLocationCoordinate2DMake(lat, lon);
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(center, radius, radius);
// line 43 and 44 creates a geofence/overlay
[self.mapView setRegion:region];
[self setUpMapViewAndPin:self.location];
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]
initWithTarget:self
action:@selector(handleLongPress:)];
[self.mapView addGestureRecognizer:longPress];
self.mapView.showsUserLocation=TRUE;
[self performSelector:@selector(openCallout:) withObject:self.mapView.userLocation afterDelay:1.0];
self.searchTextField.autocorrectionType = UITextAutocorrectionTypeYes;
}
- (void) viewDidAppear:(BOOL)animated {
[self requestLocationPermission];
self.mapView.delegate = self;
if ([self hasPreviouslySavedLocation]) {
[self showPreviouslySavedLocation];
[self dropPinAtPreviouslySavedLocation];
self.hasUserLocation = YES;
}
[self updateGeoUI];
}
//- (void)animateViewUp:(BOOL) up
//{
// const int movementDistance = 30; // tweak as needed
// const float movementDuration = 0.3f; // tweak as needed
//
// int movement = (up ? -movementDistance : movementDistance);
//
// [UIView beginAnimations: @"anim" context: nil];
// [UIView setAnimationBeginsFromCurrentState: YES];
// [UIView setAnimationDuration: movementDuration];
// // self.superview.window.frame = CGRectOffset(self.frame, 0, movement);
// // self.superview.frame = CGRectOffset(self.frame, 0, movement);
// self.frame = CGRectOffset(self.frame, 0, movement);
//
// [UIView commitAnimations];
//}
//- (void)setupTapGestureRecognizer {
// // tap to dismiss keyboard!
// UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
// initWithTarget:self
// action:@selector(dismissKeyboard)];
//
// [self.view addGestureRecognizer:tap];
// [tap setCancelsTouchesInView:YES];
//}
// CHARLES LOOK AT THIS CODE
- (void)requestLocationPermission {
self.locationManager = [[CLLocationManager alloc] init];
if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
[self.locationManager requestAlwaysAuthorization];
}
}
// CHARLES LOOK AT THIS CODE
- (BOOL)hasPreviouslySavedLocation {
// kinda hacky
MKCoordinateRegion region = [self regionForSavedLocation];
return !(region.center.latitude == 0 && region.center.longitude == 0 && region.span.longitudeDelta == 0 && region.span.latitudeDelta == 0);
}
// CHARLES LOOK AT THIS CODE
- (void)showPreviouslySavedLocation {
MKCoordinateRegion region = [self regionForSavedLocation];
[self.mapView setRegion:region animated:NO];
}
// CHARLES LOOK AT THIS CODE
- (void)dropPinAtPreviouslySavedLocation {
MKCoordinateRegion region = [self regionForSavedLocation];
MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init];
annotation.coordinate = region.center;
if (annotation) {
}
[self.mapView addAnnotation:annotation];
}
- (void) setCurrentLocation{
if (self.locationManager == nil){
self.locationManager = [[CLLocationManager alloc]init];
}
self.locationManager.delegate = self;
//mandatory check http://stackoverflow.com/questions/24062509/location-services-not-working-in-ios-8
self.locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
}
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation {
MKCoordinateRegion mapRegion;
mapRegion.center = mapView.userLocation.coordinate;
mapRegion.span = MKCoordinateSpanMake(0.005, 0.005);
// set zoom to user's location
self.location = self.locationManager.location;
// zoom to region containing the user location
// MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 800, 800);
// [self.mapView setRegion:[self.mapView regionThatFits:region] animated:YES];
if (!self.hasUserLocation) {
self.hasUserLocation = YES;
[self.mapView setRegion:mapRegion animated:YES];
// add the annotation
MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
point.coordinate = userLocation.coordinate;
}
}
- (MKOverlayView *)mapView:(MKMapView *)map viewForOverlay:(id <MKOverlay>)overlay {
MKCircleView *circleView = [[MKCircleView alloc] initWithOverlay:overlay];
circleView.fillColor = [[UIColor blueColor] colorWithAlphaComponent:0.2];
return circleView;
}
- (void)performSearch {
MKLocalSearchRequest *request =
[[MKLocalSearchRequest alloc] init];
request.naturalLanguageQuery = self.searchTextField.text;
request.region = _mapView.region;
self.matchingSearchItems = [[NSMutableArray alloc] init];
MKLocalSearch *search =
[[MKLocalSearch alloc]initWithRequest:request];
[search startWithCompletionHandler:^(MKLocalSearchResponse
*response, NSError *error) {
if (response.mapItems.count == 0) {
NSLog(@"No Matches");
} else {
MKMapItem *item = response.mapItems[0];
[self.mapView setRegion:MKCoordinateRegionMake(item.placemark.coordinate, MKCoordinateSpanMake(0.005, 0.005))];
for (MKMapItem *item in response.mapItems)
{
[self.matchingSearchItems addObject:item];
MKPointAnnotation *annotation =
[[MKPointAnnotation alloc]init];
annotation.coordinate = item.placemark.coordinate;
annotation.title = item.name;
[_mapView addAnnotation:annotation];
}
}
}];
}
- (MKCoordinateRegion)regionForSavedLocation {
MKCoordinateRegion myRegion;
myRegion.center.latitude = [[NSUserDefaults standardUserDefaults] doubleForKey:@"map.location.center.latitude"];
myRegion.center.longitude = [[NSUserDefaults standardUserDefaults] doubleForKey:@"map.location.center.longitude"];
myRegion.span.latitudeDelta = [[NSUserDefaults standardUserDefaults] doubleForKey:@"map.location.span.latitude"];
myRegion.span.longitudeDelta = [[NSUserDefaults standardUserDefaults] doubleForKey:@"map.location.span.longitude"];
return myRegion;
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
[searchBar resignFirstResponder];
[self.mapView removeAnnotations:self.mapView.annotations];
[self performSearch];
[self setCurrentLocation];
MKLocalSearchRequest *request =
[[MKLocalSearchRequest alloc] init];
request.naturalLanguageQuery = @"Places";
request.region = _mapView.region;
MKLocalSearch *search =
[[MKLocalSearch alloc]initWithRequest:request];
[search startWithCompletionHandler:^(MKLocalSearchResponse
*response, NSError *error) {
if (response.mapItems.count == 0)
NSLog(@"No Matches");
}];
}
-(MKAnnotationView*)annotationView{
MKAnnotationView *annotationView = [[MKAnnotationView alloc]initWithAnnotation:self reuseIdentifier:@"MyCustomAnimation"];
// annotationView.enabled = YES;
// annotationView.canShowCallout = YES;
// annotationView.image = [UIImage imageNamed:@"customPin.png"];
// annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
//annotationView.frame = CGRectMake(0, 0, 100, 100);
return annotationView;
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
if ([annotation isKindOfClass:[MKUserLocation class]]) {
return nil;
}
MKPinAnnotationView *pin = [[MKPinAnnotationView alloc] init];
pin.canShowCallout = YES;
pin.animatesDrop = YES;
pin.draggable = YES;
pin.rightCalloutAccessoryView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
UIButton *addButton = [UIButton buttonWithType:UIButtonTypeContactAdd];
// found a bug, add button keeps on appearing for some reason
pin.rightCalloutAccessoryView = addButton;
if ([annotation isKindOfClass:[CustomPin class]]){
CustomPin *myLocation = (CustomPin*)annotation;
MKAnnotationView *annotationView = [self.mapView dequeueReusableAnnotationViewWithIdentifier:@"customAnnotation"];
if (annotationView == nil){
annotationView = myLocation.annotationView;
} else {
annotationView.annotation = annotation;
}
return annotationView;
} else {
return pin;
}
}
- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views {
MKAnnotationView *aV;
for (aV in views) {
if ([aV.annotation isKindOfClass:[MKUserLocation class]]) {
MKAnnotationView* annotationView = aV;
annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeContactAdd];
}
}
}
- (void)handleLongPress:(UIGestureRecognizer *)gestureRecognizer
{
if (gestureRecognizer.state != UIGestureRecognizerStateBegan)
return;
[self.mapView removeAnnotations:self.mapView.annotations];
CGPoint touchPoint = [gestureRecognizer locationInView:self.mapView];
CLLocationCoordinate2D touchMapCoordinate = [self.mapView convertPoint:touchPoint toCoordinateFromView:self.mapView];
// NLMapViewController *annotation = [[NLMapViewController alloc] init];
// annotation.coordinate = touchMapCoordinate;
MKPointAnnotation *annotation =
[[MKPointAnnotation alloc]init];
annotation.coordinate = touchMapCoordinate;
annotation.title = @"Destination";
[self.mapView addAnnotation:annotation];
}
#pragma mark - create geofence when save location plus button tapped
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
// remove all existing geofences
for (CLRegion *region in self.locationManager.monitoredRegions) {
[self.locationManager stopMonitoringForRegion:region];
}
// saves the pin location and zooms the map to that pin, when a user opens the app again
CLLocationCoordinate2D location = view.annotation.coordinate;
[[NSUserDefaults standardUserDefaults] setDouble:location.latitude forKey:@"map.location.center.latitude"];
[[NSUserDefaults standardUserDefaults] setDouble:location.longitude forKey:@"map.location.center.longitude"];
[[NSUserDefaults standardUserDefaults] setDouble:0.05 forKey:@"map.location.span.latitude"];
[[NSUserDefaults standardUserDefaults] setDouble:0.05 forKey:@"map.location.span.longitude"];
CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:location radius:40.0 identifier:@"hi"];
// NSLog(@"%f, %f", region.center.latitude, region.center.longitude);
// create new geofence
[self.locationManager startMonitoringForRegion:region];
MKCoordinateRegion myRegion = [self regionForSavedLocation];
NSLog(@"%@", [NSString stringWithFormat:@"Region read : %f %f %f %f", myRegion.center.latitude, myRegion.center.longitude, myRegion.span.latitudeDelta, myRegion.span.longitudeDelta]);
NSLog(@"%@", [NSString stringWithFormat:@"Region on map: %f %f %f %f", self.mapView.region.center.latitude, self.mapView.region.center.longitude, self.mapView.region.span.latitudeDelta, self.mapView.region.span.longitudeDelta]);
NSLog(@"%@", self.locationManager);
// Update UI for new geofence
[self updateGeoUI];
CLLocation *selectedLocation = [[CLLocation alloc] initWithLatitude:location.latitude longitude:location.longitude];
[self.delegate mapView:self didSelectLocation:selectedLocation];
}
#pragma mark - setup geofence circle (UI) around the selected location
- (void)updateGeoUI {
[self.mapView removeOverlay:self.overlay];
for (CLCircularRegion *region in self.locationManager.monitoredRegions) {
self.overlay = [MKCircle circleWithCenterCoordinate:region.center radius:region.radius];
[self.mapView addOverlay:self.overlay];
}
}
// testing code below this line
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
[self.locationManager stopUpdatingLocation];
[self setUpMapViewAndPin:newLocation]; // this should be doing it too!!!
}
- (void)setUpMapViewAndPin:(CLLocation *)location {
CLLocationCoordinate2D location2D = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude);
self.mapView.delegate = self;
self.mapView.showsUserLocation = YES;
//zoom in
MKMapCamera *camera = [MKMapCamera cameraLookingAtCenterCoordinate:location2D fromEyeCoordinate:location2D eyeAltitude:10000];
[self.mapView setCamera:camera animated:NO];
}
- (void)openCallout:(id<MKAnnotation>)annotation {
[self.mapView selectAnnotation:annotation animated:NO];
}
-(void)dismissKeyboard {
[self.searchTextField resignFirstResponder];
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment