How to load the map with the obtained current location in iphone? - iphone

I am new to iphone development.I am creating a map application.I have toolbar below the mapview with a button on it.On clicking the button it displays as an alert to load the current location.In my button click even i hava given code to find current location
-(IBAction) gosearch : (id) sender{
self.locationManager = [[[CLLocationManager alloc] init] autorelease];
self.locationManager.delegate = self;
[locationManager startUpdatingLocation];
}
For me it is not displaying the alert.What should i do?Please help me out. Thanks.

You need to have your controller class implement protocol CLLocationManagerDeligate. This will mean that it gets notified of errors or when the location is posted (for example – locationManager:didUpdateToLocation:fromLocation:)
Then you can pass on the long/lat and radius of view required to the MapView

Make sure for the alert view it looks like this-
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Current Location" message:#"Show Current Location?" delegate:nil cancelButtonTitle:#"Cancel" otherButtonTitles:#"OK"];
[alert show];
and also
- (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex
{
if (buttonIndex != [alertView cancelButtonIndex])
{
map.showsuserlocation = YES;
}
}

I'm not sure I fully understand your questions but here's what I have done to use the location manager.
First, I declare a class that implements CLLocationManagerDelegate
#interface GPSComponent <CLLocationManagerDelegate> {
CLLocationManager *locationManager;
CLLocation *currentLocation;
}
Then, in the class I have:
- (id) init {
locationManager = [[CLLocationManager alloc] init];
// Provide the best possible accuracy (this is the default; just want to write some code).
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
// Must move at least 100 meters to get a new location update (default is get all notifications).
locationManager.distanceFilter = 100;
locationManager.delegate = self;
[locationManager startUpdatingLocation];
}
#pragma mark -
#pragma mark CLLocationManagerDelegate methods
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
// If you are about 400 miles south off the coast of Ghana, we might be ignoring your location information. We apologize.
// This is a lazy way to check for failure (in which case the struct is zeroed out).
if((fabs(newLocation.coordinate.latitude) > 0.001) || (fabs(newLocation.coordinate.longitude) > 0.001)) {
NSLog(#"Got location %f,%f", newLocation.coordinate.latitude, newLocation.coordinate.longitude);
if (currentLocation != nil) {
[currentLocation release];
}
currentLocation = newLocation;
[currentLocation retain];
}
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
NSLog(#"Location Manager error");
}
Then, to display a map with the user's location:
// Pull out the longitude and latitude and invoke google maps
- (IBAction)mapItButtonPressed {
NSString *url = [NSString stringWithFormat: #"http://maps.google.com/maps?q=%f,%f", (float)currentLocation.coordinate.latitude, (float)currentLocation.coordinate.longitude];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]];
}

Related

Not calling delegate on timer Objective-C

I all I wonder if anybody can help me once again? I have moved my location coding from my View controller into an NSObject. I have then called this from the App Delegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//Updating Location
[Location sharedLocation];
//Timer for reloading the XML
recheckTimer = [NSTimer scheduledTimerWithTimeInterval:30 target:self selector:#selector(recheckLocation) userInfo:nil repeats:YES];
return YES:
}
I have set a timer for when I want this process ran again
-(void)recheckLocation
{
//Updating Location
[Location sharedLocation];
NSLog(#"Timer Triggered");
}
The only thing is when the timer triggers the sharedlocation does not get updated again?? Please can anybody help in advance? Many thanks, Jon.
#import "Location.h"
#implementation Location
#synthesize locationManager;
- (id)init {
self = [super init];
if(self) {
self.locationManager = [CLLocationManager new];
[self.locationManager setDelegate:self];
[self.locationManager setDistanceFilter:500];//Metres
[self.locationManager setHeadingFilter:90];
[self.locationManager startMonitoringSignificantLocationChanges];
}
return self;
}
+ (Location*)sharedLocation {
static Location* sharedLocation;
if(!sharedLocation) {
#synchronized(sharedLocation) {
sharedLocation = [Location new];
}
}
return sharedLocation;
}
//LOCATION CODING
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"didFailWithError' %#", error);
UIAlertView *errorAlert = [[UIAlertView alloc]initWithTitle:#"Error" message:#"Failed to Get Your Current Location" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[errorAlert show];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSLog(#"didUpdateToLocation: %#", newLocation);
CLLocation *currentLocation = newLocation;
if (currentLocation != nil) {
//Resolve Web Address
webAddressResolved = [NSString stringWithFormat:#"XZYYFASDFA%f,%f.xml", currentLocation.coordinate.latitude, currentLocation.coordinate.longitude];
NSLog(#"Address Resolved %#", webAddressResolved);
}
//Stop Location Manager
[locationManager stopMonitoringSignificantLocationChanges];
}
Well what yo defined here is a singleton of Location and the purpose of shared location does not seem to update the location as it says in the code comments
what the sharedInstance does is return a reference that is once initialized and is used the same everywhere in the whole code.It gives you the location instance in return, which you are not retrieving anywhere and using it.You just call it but not use it.
Define a method to update location and call it after getting the memory from the location using
Location *sharedLoc=[Location sharedLocation];
and call the method to update the location as
[sharedLoc updateLocation];
Location.h
-(void)updateLocation;
in Location .m
-(void)updateLocation
{
//Code for updation purpose
}

CLLocationManager issue

I want to get a single location and then stop getting notification from CLLocationManager.
I do it with this:
-(id)initWithDelegate:(id <GPSLocationDelegate>)aDelegate{
self = [super init];
if(self != nil) {
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
delegate = aDelegate;
}
return self;
}
-(void)startUpdating{
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
[locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
[locationManager stopUpdatingLocation];
[delegate locationUpdate:newLocation];
}
The issue is that even when I do [locationManager stopUpdatingLocation];
in - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:
I still get notification, any idea why it happen?
Maybe try my solution. I'm build two functionals for handling LocationManger Obj.
The first function is startUpdates for handle start update location. Code look like this :
- (void)startUpdate
{
if ([self locationManager])
{
[[self locationManager] stopUpdatingLocation];
}
else
{
self.locationManager = [[CLLocationManager alloc] init];
[[self locationManager] setDelegate:self];
[[self locationManager] setDesiredAccuracy:kCLLocationAccuracyBestForNavigation];
[[self locationManager] setDistanceFilter:10.0];
}
[[self locationManager] startUpdatingLocation];
}
The second function is stopUpdate for handle CLLocationDelegate to stop update location. Code look like this :
- (void)stopUpdate
{
if ([self locationManager])
{
[[self locationManager] stopUpdatingLocation];
}
}
So, for CLLocationManagerDelegate should be look like this :
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
NSDate* eventDate = newLocation.timestamp;
NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];
self.attempts++;
if(firstPosition == NO)
{
if((howRecent < -2.0 || newLocation.horizontalAccuracy > 50.0) && ([self attempts] < 5))
{
// force an update, value is not good enough for starting Point
[self startUpdates];
return;
}
else
{
firstPosition = YES;
isReadyForReload = YES;
tempNewLocation = newLocation;
NSLog(#"## Latitude : %f", tempNewLocation.coordinate.latitude);
NSLog(#"## Longitude : %f", tempNewLocation.coordinate.longitude);
[self stopUpdate];
}
}
}
Inside this function above, i'm correct only the best location for update location. I hope my answer will help, Cheers.
I think that the reason of your problem is in distance filter. As docs say:
Use the value kCLDistanceFilterNone to be notified of all movements. The default value of this property is kCLDistanceFilterNone.
So you just have what you've set - continuous updates.

UIApplicationDelegate methods not being called

I am trying to create a plugin for region monitoring. Region Monitoring is starting fine but the function didfinishlaunching and didrecievelocalnotification are not being evoked. I am not sure why this is happening.
regionMonitoring.h
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#interface RegionMonitoringPlugin : NSObject <UIApplicationDelegate,CLLocationManagerDelegate>
{
CLLocationManager *locationManager;
}
-(void)enterRegionNotify;
-(void)leaveRegionNotify;
-(void)startMonitor:(float)latitude longitude:(float)longitude radius:(float)raduis;
#end
regionMonitoring.mm
#import "RegionMonitoringPlugin.h"
#implementation RegionMonitoringPlugin
- (id) init
{
//if ( init == [super init]){
if (locationManager==nil){
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
[locationManager setDistanceFilter:kCLDistanceFilterNone];
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
}
return self;
}
-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
[self enterRegionNotify];
}
-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
{
[self leaveRegionNotify];
}
- (void)locationManager:(CLLocationManager *)manager monitoringDidFailForRegion:(CLRegion *)regionwithError:(NSError *)error
{
NSLog(#"Location error %#, %#", error, #"Fill in the reason here");
}
-(void)leaveRegionNotify
{
NSLog(#"Starting region monitoring - check point 3");
UILocalNotification *note = [[UILocalNotification alloc] init];
note.alertBody= #"Region Left"; // ToAsk: What should be displayed
note.soundName = UILocalNotificationDefaultSoundName;
[[UIApplication sharedApplication] presentLocalNotificationNow:note];
[note release];
}
-(void)enterRegionNotify
{
UILocalNotification *note = [[UILocalNotification alloc] init];
note.alertBody= #"Region Left"; //ToAsk: what should be displayed ?
note.soundName = UILocalNotificationDefaultSoundName;
[[UIApplication sharedApplication] presentLocalNotificationNow:note];
[note release];
}
-(void)startMonitor:(float)latitude longitude:(float)longitude radius:(float)radius
{
NSLog(#"Starting region monitoring - check point 2");
[self leaveRegionNotify];
CLLocationCoordinate2D home;
home.latitude = latitude;
home.longitude = longitude;
CLRegion* region = [[CLRegion alloc] initCircularRegionWithCenter:home radius:radius identifier:#"region"];
[locationManager startMonitoringForRegion:region desiredAccuracy:kCLLocationAccuracyBest];
[region release];
}
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
NSLog(#"Starting region monitoring - checkpoint 4");
if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Region Monitor Notification" message:notification.alertBody delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
[alertView release];
}
}
- (BOOL)application:(UIApplication *) application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSLog(#"Test");
return TRUE;
}
#end
extern "C" {
static RegionMonitoringPlugin *regionMonitor;
// Unity callable function to start region monitoring
BOOL _startRegionMonitoring(float m_latitude,float m_longitude, float m_radius)
{
NSLog(#"Starting region monitoring");
if (![CLLocationManager regionMonitoringAvailable] || ![CLLocationManager regionMonitoringEnabled] )
return NO;
if (regionMonitor == nil){
regionMonitor = [[RegionMonitoringPlugin alloc] init] ;
}
[regionMonitor startMonitor:m_latitude longitude:m_longitude radius:m_radius];
return YES;
}
}
Unity Code for plugin : RegionMonitorMediater.h
using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;
public class RegionMonitoringMediator {
/*Interface to native implementation */
[DllImport ("__Internal")]
private static extern bool _startRegionMonitoring (float m_latitude,float m_longitude, float m_radius);
public static bool startRegionMonitoring (float latitude,float longitude, float radius)
{
/*Call plugin only when running on real device*/
if (Application.platform != RuntimePlatform.OSXEditor)
return _startRegionMonitoring ( latitude , longitude , radius);
else return false;
}
}
Calling region monitor
OnPress event I do
bool startedRM = RegionMonitoringMediator.startRegionMonitoring(77.0f,28.0f,10.0f);
There is only one UIApplicationDelegate allowed per app. When Unity3D builds your application for iPhone player a class AppController is generated which acts as interface.
This class is the place for inserting your code to call RegionMonitoringPlugin.
init should include a call to super at its start:
- (id) init
{
if (self = [super init])
{
// initialize everything else
}
return self;
}
note that we used assignment (=) operator, and not comparison (==) operator.

how to get the current location position in map on iphone

i am creating an application in which i want to get the current location of the user where he is and display it on the map and when the user reaches the destination location from current location the destination location should also be pointed in the map along the direction of travel.
In my xib i have added a button & on action(showDirectionsToHere) of button i have called map
I have added the following code in my appdelegate but it gives me an error:
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation{
[manager stopUpdatingLocation];
printf("\n Latitude = " "\n Longitude = " " ",[NSString stringWithFormat:#"%.7f",newLocation.coordinate.latitude],[NSString stringWithFormat:#"%.7f",newLocation.coordinate.longitude]);
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
CLLocationManager *locationManager = [[[CLLocationManager alloc]init]autorelease];
locationManager.delegate = self;
[locationManager startUpdatingLocation];
//[self.window addSubview:viewController.view];
[self.window makeKeyAndVisible];
return YES;
}
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
printf("\nerror");
}
- (IBAction)showDirectionsToHere {
CLLocationCoordinate2D currentLocation = [self getCurrentLocation]; // LINE 1
NSString* url = [NSString stringWithFormat: #"http://maps.google.com/maps?saddr=old\%20Location&daddr=%f,%f", newLocation.latitude, newLocation.longitude];//Line 2
}
in line 1 of action(showDirectionsHere) i get error of invalid initializer
in Line 2 i get error that newLocation undeclared.
Please help me
NSString* url = [NSString stringWithFormat: #"http://maps.google.com/maps?saddr=old\%20Location&daddr=%f,%f", currentLocation.latitude, currentLocation.longitude];
Can you post the code for getCurrentLocation so that we can see what it returns.
The variable newLocation is undeclared. I think you meant currentLocation in the function.

What's the easiest way to get the current location of an iPhone?

I already know how to use the CLLocationManager, so I could do it the hard way, with delegates and all that.
But I'd like to have a convenience method that just gets the current location, once, and blocks until it gets the result.
What I do is implement a singleton class to manage updates from core location. To access my current location, I do a CLLocation *myLocation = [[LocationManager sharedInstance] currentLocation]; If you wanted to block the main thread you could do something like this:
while ([[LocationManager sharedInstance] locationKnown] == NO){
//blocking here
//do stuff here, dont forget to have some kind of timeout to get out of this blocked //state
}
However, as it has been already pointed out, blocking the main thread is probably not a good idea, but this can be a good jumping off point as you are building something. You will also notice that the class I wrote checks the timestamp on location updates and ignores any that are old, to prevent the problem of getting stale data from core location.
This is the singleton class I wrote. Please note that it is a little rough around the edges:
#import <CoreLocation/CoreLocation.h>
#import <Foundation/Foundation.h>
#interface LocationController : NSObject <CLLocationManagerDelegate> {
CLLocationManager *locationManager;
CLLocation *currentLocation;
}
+ (LocationController *)sharedInstance;
-(void) start;
-(void) stop;
-(BOOL) locationKnown;
#property (nonatomic, retain) CLLocation *currentLocation;
#end
#implementation LocationController
#synthesize currentLocation;
static LocationController *sharedInstance;
+ (LocationController *)sharedInstance {
#synchronized(self) {
if (!sharedInstance)
sharedInstance=[[LocationController alloc] init];
}
return sharedInstance;
}
+(id)alloc {
#synchronized(self) {
NSAssert(sharedInstance == nil, #"Attempted to allocate a second instance of a singleton LocationController.");
sharedInstance = [super alloc];
}
return sharedInstance;
}
-(id) init {
if (self = [super init]) {
self.currentLocation = [[CLLocation alloc] init];
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
[self start];
}
return self;
}
-(void) start {
[locationManager startUpdatingLocation];
}
-(void) stop {
[locationManager stopUpdatingLocation];
}
-(BOOL) locationKnown {
if (round(currentLocation.speed) == -1) return NO; else return YES;
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
//if the time interval returned from core location is more than two minutes we ignore it because it might be from an old session
if ( abs([newLocation.timestamp timeIntervalSinceDate: [NSDate date]]) < 120) {
self.currentLocation = newLocation;
}
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
UIAlertView *alert;
alert = [[UIAlertView alloc] initWithTitle:#"Error" message:[error description] delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
[alert release];
}
-(void) dealloc {
[locationManager release];
[currentLocation release];
[super dealloc];
}
#end
There is no such convenience and you shouldn't create your own. "Blocks until it gets the result" is extremely bad programming practice on a device like the iPhone. It can take seconds to retrieve a location; you should never make your users wait like that, and delegates ensure they don't.
There are no "convenience methods" unless you code them yourself, but you'd still need to implement the delegate methods in whatever custom code you use to make things "convenient."
The delegate pattern is there for a reason, and as delegates are a big part of Objective-C, I recommend you get comfortable with them.
I appreciated the answer by Brad Smith. Implementing it I discovered that one of the methods he employs is deprecated as of iOS6. To write code that will work with both iOS5 and iOS6, use the following:
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
if (abs([[locations lastObject] timeIntervalSinceDate:[NSDate date]]) < 120) {
[self setCurrentLocation:[locations lastObject]];
}
}
// Backward compatibility with iOS5.
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
NSArray *locations = [NSArray arrayWithObjects:oldLocation, newLocation, nil];
[self locationManager:manager didUpdateLocations:locations];
}
I simplified and combined multiple answers to where the location is only updated if it's valid.
It also works under OSX as well as iOS.
This assumes the use-case where the current location is suddenly desired by the user. If it takes more than 100 ms in this example, it's considered an error. (Assumes the GPS IC &| Wifi (Apple's Skyhook clone) is already fired up and has a good fix already.)
#import "LocationManager.h"
// wait up to 100 ms
CLLocation *location = [LocationManager currentLocationByWaitingUpToMilliseconds:100];
if (!location) {
NSLog(#"no location :(");
return;
}
// location is good, yay
https://gist.github.com/6972228