I'm doing the homework from the Big Nerd Ranch Guide. I can't get my map to show a new location. I know I'm using one deprecated method but I was having a problem using NSArray (the deprecated method is locationManager:didUpdateToLocation:fromLocation). Any pointers would be appreciated.
Here's my code:
WhereamiViewController.h:
// WhereamiViewController.h
// Whereami
//
// Created by Meghan on 2/28/14.
// Copyright (c) 2014 Meghan. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
#interface WhereamiViewController : UIViewController <CLLocationManagerDelegate, MKMapViewDelegate, UITextFieldDelegate>
{
CLLocationManager *locationManager;
IBOutlet UITextField *locationTitleField;
IBOutlet UIActivityIndicatorView *activityIndicator;
IBOutlet MKMapView *worldView;
}
- (void)findLocation;
- (void)foundLocation:(CLLocation *)loc;
#end
WhereamiViewController.m:
// WhereamiViewController.m
// Whereami
//
// Created by Meghan on 2/28/14.
// Copyright (c) 2014 Meghan. All rights reserved.
//
#import "WhereamiViewController.h"
#import "BNRMapPoint.h"
#interface WhereamiViewController ()
#end
#implementation WhereamiViewController
- (void)findLocation
{
[locationManager startUpdatingLocation];
[activityIndicator startAnimating];
[locationTitleField setHidden:YES];
}
- (void)foundLocation:(CLLocation *)loc
{
CLLocationCoordinate2D coord = [loc coordinate];
//Create an instance of BNRMapPoint with the current data
BNRMapPoint *mp = [[BNRMapPoint alloc]initWithCoordinate:coord
title:[locationTitleField text]];
//Add it to the map view
[worldView addAnnotation:mp];
//Zoom the region to this location
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(coord, 250, 250);
[worldView setRegion:region animated:YES];
//Reset the UI
[locationTitleField setText:#""];
[activityIndicator stopAnimating];
[locationTitleField setHidden:NO];
[locationManager stopUpdatingLocation];
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
//Create location manager object
locationManager = [[CLLocationManager alloc] init];
[locationManager setDelegate:self];
//We want the most accuracy
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
//Tell our manager to start looking for location immediately
[locationManager startUpdatingHeading];
[locationManager setDistanceFilter:50];
}
return self;
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
NSLog(#"%#", newLocation);
//How many seconds ago was this new location created?
NSTimeInterval t = [[newLocation timestamp] timeIntervalSinceNow];
//CLLocationManagers will return the last found location of the
//device first, you don't want that data in this case.
//If this location was made > 3 minutes ago, ignore it
if (t < -180) {
//This is cached data, you don't want it. Keep looking.
return;
}
[self foundLocation:newLocation];
}
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error
{
NSLog(#"Could not find location: %#", error);
}
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
{
int degrees = (int)locationManager.heading.magneticHeading;
NSLog(#"from delegate method: %i", degrees);
}
- (void)dealloc
{
//Tell loc manager to stop sending messages
[locationManager setDelegate:nil];
}
- (void)viewDidLoad
{
[worldView setShowsUserLocation:YES];
}
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
CLLocationCoordinate2D loc = [userLocation coordinate];
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(loc, 250, 250);
[worldView setRegion:region animated:YES];
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
//This method isn't implemented yet - but will be soon.
[self findLocation];
[textField resignFirstResponder];
return YES;
}
#end
BNRMapPoint.h:
// BNRMapPoint.h
// Whereami
//
// Created by Meghan on 3/4/14.
// Copyright (c) 2014 Meghan. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
#interface BNRMapPoint : NSObject <MKAnnotation>
{
}
//A new designated initializer for instances of BNRMapPoint
- (id)initWithCoordinate:(CLLocationCoordinate2D)c title:(NSString *)t;
//This is a required property from MKAnnotation
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
//This is an optional property from MKAnnotation
#property (nonatomic, copy) NSString *title;
#end
BNRMapPoint.m:
// BNRMapPoint.m
// Whereami
//
// Created by Meghan on 3/4/14.
// Copyright (c) 2014 Meghan. All rights reserved.
//
#import "BNRMapPoint.h"
#implementation BNRMapPoint
- (id)initWithCoordinate:(CLLocationCoordinate2D)c title:(NSString *)t
{
self = [super init];
if (self) {
_coordinate = c;
[self setTitle:t];
}
return self;
}
- (id)init
{
return [self initWithCoordinate:CLLocationCoordinate2DMake(43.07, -89.32)
title:#"Hometown"];
}
#end
In the initWithNibName method, you're not calling startUpdatingLocation on the locationManager (you're only calling startUpdatingHeading).
(You are calling startUpdatingLocation in findLocation but that's only called from textFieldShouldReturn.)
The didUpdateToLocation delegate method is only called if you do startUpdatingLocation.
Also, make sure the initWithNibName method is actually getting called.
Depending on how this view controller is being created, you may need to move that startup code to initWithCoder: or viewDidLoad.
Hey you can get updated location from this method in iOS
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
location_updated = [locations lastObject];
NSLog(#"updated coordinate are %#",location_updated);
}
Related
Im trying to get the current user location on the map view and have it be zoomed in on.
This my code-
#import "WhereamiAppDelegate.h"
#import "WhereamiViewController.h"
#implementation WhereamiAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[WhereamiViewController alloc] initWithNibName:#"WhereamiViewController" bundle:nil];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
#interface WhereamiViewController : UIViewController<CLLocationManagerDelegate,MKMapViewDelegate,UITextFieldDelegate>
{
//#public RootObject *rootObj;
CLLocationManager *locationManager;
IBOutlet MKMapView *worldView;
IBOutlet UIActivityIndicatorView *activityIndicator;
IBOutlet UITextField *locationTitleField;
}
-(IBAction)buttonDidGetPressed:(id)sender;
-(BOOL)textFieldShouldReturn:(UITextField *)textField;
-(void)findLocation;
-(void)foundLocation:(CLLocation *)loc;
#end
#implementation WhereamiViewController
-(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{
NSLog(#"%#", NSStringFromSelector(_cmd));
if (self=[super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
// rootObj= [[RootObject alloc] init];//RootObject initialised
// NSLog(#"RootObject–– %#",rootObj);
locationManager= [[CLLocationManager alloc] init];
[locationManager setDelegate:self];//self is Whereamicontroller. The delegate pointer is of type id<CLLocationManagerDelegate> and is an ivar of CLLocationManager.
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
}
return self;
}
-(void) viewDidLoad{
NSLog(#"%#",NSStringFromSelector(_cmd));
worldView.showsUserLocation=YES;
}
-(void)mapViewWillStartLocatingUser:(MKMapView *)mapView{
NSLog(#"%#", NSStringFromSelector(_cmd));
}
-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation{
NSLog(#"%#",NSStringFromSelector(_cmd));
CLLocationCoordinate2D centerCoordinate= [userLocation coordinate]; //get the coordinate of current location.
NSLog(#"%# (%f, %f)",userLocation.location,centerCoordinate.latitude,centerCoordinate.longitude);
MKCoordinateSpan span= MKCoordinateSpanMake(250, 250);//Structure members
MKCoordinateRegion mapPortionToDisplay= MKCoordinateRegionMakeWithDistance(centerCoordinate, span.latitudeDelta, span.longitudeDelta);//span.latitudeDelta=250 and span.longitudeDelta=250
[worldView setRegion:mapPortionToDisplay animated:YES];
// [worldView setRegion:mapPortionToDisplay];
[worldView regionThatFits:mapPortionToDisplay];
}
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{ //CLLocationManagerDelegate method implementation
NSLog(#"%#", NSStringFromSelector(_cmd));
// NSTimeInterval t0=[[locations lastObject] timeIntervalSinceNow];
NSLog(#"current location–– %#",(CLLocation *)[locations lastObject]);
}
Following is the output-
2017-08-25 22:16:19.178 Whereami2[1601:758525] initWithNibName:bundle:
2017-08-25 22:16:19.294 Whereami2[1601:758525] viewDidLoad
2017-08-25 22:16:20.607 Whereami2[1601:758525] mapViewWillStartLocatingUser:
From the above lines, its clearly seen that mapView:didUpdateUserLocation: message did not get passed to map view's delegate at all. Same is the case with locationManager:didUpdateLocations:. The showsUserLocations property is supposed to send CLLocationManager's delegate, a viewcontroller (which is the same as MKMapView's delegate), this message also in its implementation. Is it not?
You've declared locationManager as an instance variable without synthesizing it's getters and setters. It's probably being deallocated. Just make it a property:
#interface WhereamiViewController : UIViewController <CLLocationManagerDelegate, MKMapViewDelegate, UITextFieldDelegate>
#property (nonatomic, strong) CLLocationManager *locationManager;
#end
As for the worldView, I don't see where you're setting something like worldView.delegate = self
I checked many links and googled it a lot. I tried those codes too but didn't succeeded so at last i am posting it here.
can any one help me regarding user location update.
I know how to show user current location it's just a check
showUserLocation.
I know there is location Manage and delegate for location keep updates.
I tried few code in which people are updating the map in location manager update delegate. But it's not working for me.It just show the blue point on user current location but it's not keep updating if i move.
So, can any one guide me from start that what should i do. How to show the User current location keep update on map when ever or where ever user move.
please try using this method
Don't forget to add CLLocationManagerDelegate and MKMapviewDelegate in your header File.
first implement the below line into your reload map method or viewDidload or viewWillappear method:
[mapView setShowsUserLocation:YES]
Than change the below methods like this:
(MKAnnotationView *) mapView:(MKMapView *)mapsView viewForAnnotation:(id <MKAnnotation>) annotation
{
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
}
You can do it by yourself without using showUserLocation
You should use CLLocationManager to get current location and add it into mapView
Implement MKAnnotation
#interface MyAnnotation : NSObject<MKAnnotation>{
CLLocationCoordinate2D _coordinate;
NSString *_title;
NSString *_subtitle;
}
- (id)initWithCoordinate:(CLLocationCoordinate2D)coordinate title:(NSString *)title subtitle:(NSString *)subtitle;
#end
#implementation MyAnnotation
- (NSString *)title {return _title;}
- (NSString *)subtitle {return _subtitle;}
- (CLLocationCoordinate2D)coordinate {return _coordinate;}
- (void)setCoordinate:(CLLocationCoordinate2D)newCoordinate {_coordinate = newCoordinate;}
- (id)initWithCoordinate:(CLLocationCoordinate2D)coordinate title:(NSString *)title subtitle:(NSString *)subtitle {
if (self = [super init]) {
_title = title.copy;
_subtitle = subtitle.copy;
_coordinate = coordinate;
}
return self;
}
#end
Create 1 UIViewController
#interface MyViewController () <CLLocationManagerDelegate>{
CLLocationManager *locationManager;
MyAnnotation *userAnnotation;
}
#property (strong, nonatomic) MKMapView *mapView;
#end
#implementation MyViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.mapView = [[MKMapView alloc] initWithFrame:self.view.bounds];
self.mapView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
[self.view addSubview:self.mapView];
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
}
#pragma mark - DELEGATE
//for iOS 5
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
// [manager stopUpdatingLocation];
if (newLocation) {
if (!userAnnotation) {
userAnnotation = [[MyAnnotation alloc]
initWithCoordinate:newLocation.coordinate
title:#"I'm here"
subtitle:nil];
[self.mapView addAnnotation:userAnnotation];
} else {
[self.mapView removeAnnotation:userAnnotation];
[userAnnotation setCoordinate:newLocation.coordinate];
[self.mapView addAnnotation:userAnnotation];
}
}
}
//for iOS 6
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
CLLocation *loc = locations.lastObject;
[self locationManager:manager didUpdateToLocation:loc fromLocation:nil];
}
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error {
//open GPS services please
}
- (void)dealloc {
[locationManager stopUpdatingLocation];
}
#end
Note:
Remember remove old annotation and add it again when receiving new
location
Please use iOS 5 and ARC
new to objective c!
Im trying to make my mapview zoom. I've copied some code from a assignment in my book, but it somehow doesn't zoom. Just shows the unzoomed mapview.
Any suggestions? See The viewController code below.
Also - a few words on the difference of importing a header file and the #class directive would be great!?
Thanks in advance
#import "TrackViewController.h"
#import "MainWindowViewController.h"
#import <MapKit/MapKit.h>
#class MainWindowViewController;
#implementation TrackViewController
- (id) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self=[super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if(self)
{
locationManager = [[CLLocationManager alloc]init];
[locationManager setDelegate:self];
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
}
return self;
}
-(IBAction) back:(id)sender
{
[self dismissViewControllerAnimated:YES completion:nil];
}
-(void) findLocation;
{
[locationManager startUpdatingLocation];
}
-(void) foundLocation:(CLLocation *)loc
{
CLLocationCoordinate2D coord = [loc coordinate];
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(coord, 100, 100);
[worldView setRegion:region];
[locationManager stopUpdatingLocation];
}
-(void)viewDidLoad
{
[worldView setShowsUserLocation:YES];
[worldView setMapType:MKMapTypeHybrid];
}
-(void)dealloc
{
[locationManager setDelegate:nil];
}
- (void) locationManager:(CLLocationManager *) manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
NSTimeInterval t = [[newLocation timestamp] timeIntervalSinceNow];
if(t<180){
return;
}
[self foundLocation:newLocation];
}
-(void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error
{
NSLog(#"Could not find location: %#", error);
}
#end
The only thing I notice is to change your setRegion line to:
[worldView setRegion:region animated:YES];//instead of just setRegion
-The setRegion: documentation states:
The area currently displayed by the map view
-While the setRegion:animated: documentation states:
Changes the currently visible region and optionally animates the change
Otherwise, I recommend printing out your CLLocationCoordinate2D object and ensuring it is valid.
I am working on an iOS application and want to include the Breadcrumb iOS Mapkit route functionality provided by apple as one of the feature. I have created a UIViewController in the storyboard (as a tab from a tab bar controller) and inserted a MKMapView in it. I have also connected it to the outlet in ThirdViewController shown below. The classes are shown below. I have classes CrumbPath and CrumbPathView exactly as in the Breadcrumb example at http://developer.apple.com/library/ios/#samplecode/Breadcrumb/Introduction/Intro.html
Even with the same code, the mkoverlay route does not show in my app. Am I missing something important here. I am not experienced in iOS programming and may have missed something basic.
ThirdViewController.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import "CrumbPath.h"
#import "CrumbPathView.h"
#interface ThirdViewController : UIViewController <MKMapViewDelegate, CLLocationManagerDelegate>
{
#private
MKMapView *map;
CrumbPath *crumbs;
CrumbPathView *crumbView;
CLLocationManager *locationManager;
}
#property (nonatomic, retain) IBOutlet MKMapView *map;
#property (nonatomic, retain) CLLocationManager *locationManager;
#end
ThirdViewController.m
#import "ThirdViewController.h"
#interface ThirdViewController ()
#end
#implementation ThirdViewController
#synthesize locationManager, map;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.wantsFullScreenLayout = YES;
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[self.locationManager startUpdatingLocation];
[self.view addSubview:self.map];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
self.map = nil;
self.locationManager.delegate = nil;
self.locationManager = nil;
}
-(void) dealloc
{
}
- (BOOL)shouldAutorotateToInterfaceOrientation (UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#pragma mark -
#pragma mark MapKit
- (void) locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
if(newLocation)
{
if((oldLocation.coordinate.latitude != newLocation.coordinate.latitude) && (oldLocation.coordinate.longitude != newLocation.coordinate.longitude))
{
if(!crumbs)
{
crumbs = [[CrumbPath alloc] initWithCenterCoordinate:newLocation.coordinate];
[map addOverlay:crumbs];
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(newLocation.coordinate, 2000, 2000);
[map setRegion:region animated:YES];
}
else
{
MKMapRect updateRect = [crumbs addCoordinate:newLocation.coordinate];
if(!MKMapRectIsNull(updateRect))
{
MKZoomScale currentZoomScale = (CGFloat)(map.bounds.size.width/map.visibleMapRect.size.width);
CGFloat lineWidth = MKRoadWidthAtZoomScale(currentZoomScale);
updateRect = MKMapRectInset(updateRect, -lineWidth, -lineWidth);
[crumbView setNeedsDisplayInMapRect:updateRect];
}
}
}
}
}
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay
{
if(!crumbView)
{
crumbView = [[CrumbPathView alloc] initWithOverlay:overlay];
}
return crumbView;
}
#end
You didn't have your ThirdViewController set as the delegate to your MKMapView in your storyboard, so mapView:viewForOverlay: was never being called. Setting the delegate property fixes the problem.
I've currently got a map that shows the user's current location and also has a couple of annotation markers (I have yet to put them in an array but will soon). I'm trying to get my iphone app to trigger an alert when the user reaches certain locations. How do I do that? Here's what I have right now...
ViewController.h
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
#import "MapAnnotation.h"
#interface ViewController : UIViewController <CLLocationManagerDelegate, MKMapViewDelegate>
{
CLLocationManager *locationManager;
IBOutlet MKMapView *worldView;
}
#end
view controller.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[worldView setShowsUserLocation:YES];
}
- (void)mapView:(MKMapView *)mapView
didUpdateUserLocation:(MKUserLocation *)userLocation
{
CLLocationCoordinate2D loc = [userLocation coordinate];
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(loc, 250, 250);
[worldView setRegion:region animated:YES];
MKCoordinateRegion pin = { {0.0, 0.0 }, {0.0, 0.0 } };
pin.center.latitude = 53.363581;
pin.center.longitude = -6.258183;
pin.span.longitudeDelta = 0.01f;
pin.span.latitudeDelta = 0.01f;
[worldView setRegion:pin animated:YES];
MapAnnotation *stage1 = [[MapAnnotation alloc] init];
stage1.title = #"Quinn's";
stage1.coordinate = pin.center;
[worldView addAnnotation:stage1];
MKCoordinateRegion pin2 = { {0.0, 0.0 }, {0.0, 0.0 } };
pin2.center.latitude = 53.364678;
pin2.center.longitude = -6.263009;
pin2.span.longitudeDelta = 0.01f;
pin2.span.latitudeDelta = 0.01f;
[worldView setRegion:pin2 animated:YES];
MapAnnotation *stage2 = [[MapAnnotation alloc] init];
stage2.title = #"Neighbour";
stage2.coordinate = pin2.center;
[worldView addAnnotation:stage2];
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Create location manager object
locationManager = [[CLLocationManager alloc] init];
// Setting Delegate as AnotherMapFirstViewController
[locationManager setDelegate:self];
// And we want it to be as accurate as possible
// regardless of how much time/power it takes
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
self.title = NSLocalizedString(#"First", #"First");
self.tabBarItem.image = [UIImage imageNamed:#"first"];
}
return self;
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
NSLog(#"%#", newLocation);
}
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error
{
NSLog(#"Could not find location: %#", error);
}
- (void)dealloc
{
// Tell the location manager to stop sending us messages
[locationManager setDelegate:nil];
}
#end
You want to look for region monitoring. Check the documentation for -[CLLocationManager startMonitoringForRegion:].