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.
Related
I have a UIViewController where I want to display a map centered on current position.
AppDelegate's didFinishLaunchingWithOptions method looks like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.locationManager = [[CLLocationManager alloc] init];
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined) {
[self.locationManager requestAlwaysAuthorization];
}
[self.locationManager startUpdatingLocation];
return YES;
}
My UIViewController.m class looks like this:
#interface GMapViewController ()<CLLocationManagerDelegate>
#property (weak, nonatomic) IBOutlet MKMapView *mapView;
#property (strong, nonatomic) CLLocation *currentLocation;
#end
#implementation GMapViewController
#pragma mark - Lifecycle methods
- (void)viewDidLoad {
[super viewDidLoad];
self.currentLocation = [CLLocation new];
[[[AppDelegate appDelegate] locationManager] setDelegate:self];
MKCoordinateRegion visibleRegion;
visibleRegion.center = self.currentLocation.coordinate;
visibleRegion.span = MKCoordinateSpanMake(200, 200);
[self.mapView setRegion:visibleRegion animated:YES];
}
#pragma mark - CLLocationManagerDelegate's methods
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
self.currentLocation = [locations lastObject];
}
The thing is the CLLocationManager's didUpdateLocations delegate method is called too late as the currentLocation property has no value when the viewDidLoad is called.
How can I get the current coordinate before viewDidLoad being called ?
You need to refresh your map view once the location has been updated; this will take some time.
You also have a potential race condition, because you call startUpdatingLocation in your AppDelegate, but the view controller isn't set as the delegate until viewDidLoad. The delegate will almost certainly be set before the location is updated, but you can't guarantee this.
I would suggest that you move everything into your view controller and if you only want to update the map once, use requestLocation:
#interface GMapViewController ()<CLLocationManagerDelegate>
#property (weak, nonatomic) IBOutlet MKMapView *mapView;
#property (strong, nonatomic) CLLocation *currentLocation;
#property (strong, nonatomic) CLLocationManager *locationManager;
#end
#implementation GMapViewController
#pragma mark - Lifecycle methods
- (void)viewDidLoad {
[super viewDidLoad];
self.locationManager = [[CLLocationManager alloc] init];
self.currentLocation = nil;
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined) {
[self.locationManager requestAlwaysAuthorization];
} else {
[self.locationManager requestLocation];
}
-(void) setMapTo:(CLLocation *)location {
MKCoordinateRegion visibleRegion;
visibleRegion.center =location.coordinate;
visibleRegion.span = MKCoordinateSpanMake(200, 200);
[self.mapView setRegion:visibleRegion animated:YES];
}
#pragma mark - CLLocationManagerDelegate's methods
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
CLLocation *currentLocation = [locations lastObject];
dispatch_async(dispatch_get_main_queue(), ^{
[self setMapTo:currentLocation];
});
}
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
if (status != kCLAuthorizationStatusRestricted && status != kCLAuthorizationStatusDenied) {
[manager requestLocation];
}
}
If you just want the map to track the user's location continually then you can simply set the map view's userTrackingMode property to MKUserTrackingModeFollow
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'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);
}
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
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:].