Getting user location not working? - ios

I am new to the MapView topic.Now I am working on the map view.I am getting the san Francisco location longitude and latitude values.I am testing in the simulator.It is not showing the current location longitude and latitude values.
With the help of this tutorial http://www.creativeworkline.com/2014/12/core-location-manager-ios-8-fetching-location-background/ I am developing the app.
In AppDelegate file I wrote the following code like this
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIAlertView * alert;
//We have to make sure that the Background App Refresh is enable for the Location updates to work in the background.
if([[UIApplication sharedApplication] backgroundRefreshStatus] == UIBackgroundRefreshStatusDenied){
alert = [[UIAlertView alloc]initWithTitle:#""
message:#"The app doesn't work without the Background App Refresh enabled. To turn it on, go to Settings > General > Background App Refresh"
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil, nil];
[alert show];
}else if([[UIApplication sharedApplication] backgroundRefreshStatus] == UIBackgroundRefreshStatusRestricted){
alert = [[UIAlertView alloc]initWithTitle:#""
message:#"The functions of this app are limited because the Background App Refresh is disable."
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil, nil];
[alert show];
} else{
self.locationTracker = [[LocationTracker alloc]init];
[self.locationTracker startLocationTracking];
//Send the best location to server every 60 seconds
//You may adjust the time interval depends on the need of your app.
NSTimeInterval time = 60.0;
self.locationUpdateTimer =
[NSTimer scheduledTimerWithTimeInterval:time
target:self
selector:#selector(updateLocation)
userInfo:nil
repeats:YES];
}
return YES;
}
I have imported Location Tracker class in my ViewController
and I wrote the following code to get the location name and addresss
CLGeocoder *geoCoder = [[CLGeocoder alloc]init];
__block NSString *returnAddress = nil;
[geoCoder reverseGeocodeLocation:self.appDelgate.locationTracker.myLastLocation_ completionHandler:^(NSArray *placemarks, NSError *error) {
CLPlacemark *placemark = [placemarks lastObject];
if (placemark)
{
returnAddress = [NSString stringWithFormat:#"%# %#",placemark.subLocality,placemark.subAdministrativeArea];
[[NSUserDefaults standardUserDefaults] setObject:[NSString stringWithString:returnAddress] forKey:#"address"];
}
}];
Now my problem is that it is not going inside block.So that I am getting the "returnAddress" as (null).
I wrote like this even though it is not coming
- (void)updateLocationToServer {
NSLog(#"updateLocationToServer");
// Find the best location from the array based on accuracy
NSMutableDictionary * myBestLocation = [[NSMutableDictionary alloc]init];
for(int i=0;i<self.shareModel.myLocationArray.count;i++){
NSMutableDictionary * currentLocation = [self.shareModel.myLocationArray objectAtIndex:i];
if(i==0)
myBestLocation = currentLocation;
else{
if([[currentLocation objectForKey:ACCURACY]floatValue]<=[[myBestLocation objectForKey:ACCURACY]floatValue]){
myBestLocation = currentLocation;
}
}
}
NSLog(#"My Best location:%#",myBestLocation);
NSLog(#"latitude %#",[myBestLocation valueForKey:#"latitude"]);
NSLog(#"longitude %#",[myBestLocation valueForKey:#"longitude"]);
self.DICT=[NSDictionary dictionaryWithDictionary:myBestLocation];
//If the array is 0, get the last location
//Sometimes due to network issue or unknown reason, you could not get the location during that period, the best you can do is sending the last known location to the server
if(self.shareModel.myLocationArray.count==0)
{
NSLog(#"Unable to get location, use the last known location");
self.myLocation=self.myLastLocation;
self.myLocationAccuracy=self.myLastLocationAccuracy;
}else{
CLLocationCoordinate2D theBestLocation;
theBestLocation.latitude =[[myBestLocation objectForKey:LATITUDE]floatValue];
theBestLocation.longitude =[[myBestLocation objectForKey:LONGITUDE]floatValue];
self.myLocation=theBestLocation;
self.myLocationAccuracy =[[myBestLocation objectForKey:ACCURACY]floatValue];
}
NSLog(#"Send to Server: Latitude(%f) Longitude(%f) Accuracy(%f)",self.myLocation.latitude, self.myLocation.longitude,self.myLocationAccuracy);
//TODO: Your code to send the self.myLocation and self.myLocationAccuracy to your server
//After sending the location to the server successful, remember to clear the current array with the following code. It is to make sure that you clear up old location in the array and add the new locations from locationManager
[self.shareModel.myLocationArray removeAllObjects];
self.shareModel.myLocationArray = nil;
self.shareModel.myLocationArray = [[NSMutableArray alloc]init];
CLGeocoder *geoCoder = [[CLGeocoder alloc]init];
__block NSString *returnAddress = nil;
self.locationActual = [[CLLocation alloc]initWithLatitude:[[myBestLocation objectForKey:LATITUDE]floatValue] longitude:[[myBestLocation objectForKey:LONGITUDE]floatValue]];
//CLGeocoder *geoCoder = [[CLGeocoder alloc]init];
// __block NSString *returnAddress = nil;
CLLocation *locloc = [[CLLocation alloc] initWithLatitude:[[myBestLocation objectForKey:LATITUDE]floatValue] longitude:[[myBestLocation objectForKey:LONGITUDE]floatValue]];
[geoCoder reverseGeocodeLocation:locloc completionHandler:^(NSArray *placemarks, NSError *error) {
CLPlacemark *placemark = [placemarks lastObject];
if (placemark)
{
returnAddress = [NSString stringWithFormat:#"%# %#",placemark.subLocality,placemark.subAdministrativeArea];
//[[NSUserDefaults standardUserDefaults] setObject:[NSString stringWithString:returnAddress] forKey:#"address"];
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"" message:returnAddress delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alertView show];
}
}];
}
What mistake i have done here.
Can anyone please help to clear this confusion.
Thanks in Advance.

Are you sure you are using the return address after completion block? I have used the above code and its working fine.
Here you can download the sample code
CLGeocoder *geoCoder = [[CLGeocoder alloc]init];
__block NSString *returnAddress = nil;
CLLocation *locloc = [[CLLocation alloc] initWithLatitude:12.92243 longitude:80.23893];
[geoCoder reverseGeocodeLocation:locloc completionHandler:^(NSArray *placemarks, NSError *error) {
CLPlacemark *placemark = [placemarks lastObject];
if (placemark)
{
returnAddress = [NSString stringWithFormat:#"%# %#",placemark.subLocality,placemark.subAdministrativeArea];
//[[NSUserDefaults standardUserDefaults] setObject:[NSString stringWithString:returnAddress] forKey:#"address"];
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"" message:returnAddress delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alertView show];
}
}];
//If you try to access retunAddress here you will get nil.
OUTPUT

Go to iOS Simulator -> Debug -> Location -> Custom location... And enter your long/lat coordinates.

In the simulator there is no way to get the actual GPS based data so you need to simulate is with your lat-long which you can set by going
Debug -> Location -> Custom Location
and set your values there.

Probably you are simulating the location in the simulator. In your xCode's console panel there is an arrow button. Click that button and select "Don't simulate location". For reference, see the image.
If that doesn't resolve the problem then run the application. Go into the Debug menu of the simulator and choose the "Custom location" option as shown in the image.

Related

Share location on Facebook wall using Social framework

I am trying to integrate Sharing on Facebook Login in my application but somehow i am not able to achieve this for sharing the location on the Facebook wall, here i am using the social framework.
The code i tried is as follows :
SLComposeViewController *fbController=[SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
if([SLComposeViewController isAvailableForServiceType:SLServiceTypeFacebook])
{
SLComposeViewControllerCompletionHandler __block completionHandler=^(SLComposeViewControllerResult result){
[fbController dismissViewControllerAnimated:YES completion:nil];
switch(result){
case SLComposeViewControllerResultCancelled:
default:
{
NSLog(#"Cancelled.....");
// [[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"prefs://"]];
}
break;
case SLComposeViewControllerResultDone:
{
NSLog(#"Posted....");
}
break;
}};
[fbController setInitialText:#"This is My Sample Text"];
[fbController setCompletionHandler:completionHandler];
[self presentViewController:fbController animated:YES completion:nil];
}
else{
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Sign in!" message:#"Please first Sign In!" delegate:nil cancelButtonTitle:#"ok" otherButtonTitles:nil, nil];
[alert show];
}
by this I can share the Initial text but what i need is to share is the current location.
Thanks in Advance.
u can get current location using CLLocationManger as for this import MapKit framework.
NSString *city;
CLLocationManager *locationManager;
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
CLLocationCoordinate2D coordinate = [locationManager.location coordinate];
GeoCodeValue=[[NSString alloc] initWithFormat:#"%f,%f",coordinate.latitude,coordinate.longitude];
NSLog(#"userLocation::%#",GeoCodeValue);
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:locationManager.location completionHandler:^(NSArray *placemarks, NSError *error) {
CLPlacemark *placemark = [placemarks objectAtIndex:0];
city = placemark.thoroughfare;
}];
& pass this city string as text to show current location.as
[fbController setInitialText:#"Current Location is %#",city"];

Location Issue in iPhone Device

I want to detecting user's current location in my app.I am using objective c.It's working fine in simulator but while testing on device below error comes.
didFailWithError: Error Domain=kCLErrorDomain Code=0 "The operation couldn’t be completed. (kCLErrorDomain error 0.)"
Please Help me to solve this issue.I am using Lat long value for find out place mark in my application.
if(version<8.0)
{
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
}
else
{
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
// Check for iOS 8. Without this guard the code will crash with "unknown selector" on iOS 7.
if ([locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[locationManager requestWhenInUseAuthorization];
}
[locationManager startUpdatingLocation];
}
Here are delegate method
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
NSLog(#"didFailWithError: %#", error);
UIAlertView *errorAlert = [[UIAlertView alloc]
initWithTitle:#"Error" message:#"Failed to Get Your 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) {
NSString *longitude = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.longitude];
NSString *latitude = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.latitude];
CLGeocoder * geoCoder = [[CLGeocoder alloc] init];
[geoCoder reverseGeocodeLocation: locationManager.location completionHandler:
^(NSArray *placemarks, NSError *error) {
CLPlacemark *placemark = [placemarks objectAtIndex:0];
NSString *placemark_str = [placemark locality];
subAdminArea.text=placemark.subAdministrativeArea;
NSString *are_str = [placemark subLocality];
subAdminArea.text=placemark.subAdministrativeArea;
NSString *location_str=[NSString stringWithFormat:#"%#,%#",are_str,placemark_str];
[[NSUserDefaults standardUserDefaults]setValue:location_str forKey:#"Location"];
NSLog(#"place mark str: %#",placemark_str);
}];
}}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
NSLog(#"%#", [locations lastObject]);
CLGeocoder * geoCoder = [[CLGeocoder alloc] init];
[geoCoder reverseGeocodeLocation: [locations lastObject] completionHandler:
^(NSArray *placemarks, NSError *error) {
CLPlacemark *placemark = [placemarks objectAtIndex:0];
NSString *placemark_str = [placemark locality];
NSString *are_str = [placemark subLocality];
NSString *location_str=[NSString stringWithFormat:#"%#,%#",are_str,placemark_str];
[[NSUserDefaults standardUserDefaults]setValue:location_str forKey:#"Location"];
}];}
- (void)requestAlwaysAuthorization{
CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
// If the status is denied or only granted for when in use, display an alert
if (status == kCLAuthorizationStatusAuthorizedWhenInUse || status == kCLAuthorizationStatusDenied) {
NSString *title;
title = (status == kCLAuthorizationStatusDenied) ? #"Location services are off" : #"Background location is not enabled";
NSString *message = #"To use background location you must turn on 'Always' in the Location Services Settings";
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:title
message:message
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Settings", nil];
[alertView show];
}
// The user has not enabled any location services. Request background authorization.
else if (status == kCLAuthorizationStatusNotDetermined) {
[locationManager requestAlwaysAuthorization];
}}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if (buttonIndex == 1) {
// Send the user to the Settings for this app
NSURL *settingsURL = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
[[UIApplication sharedApplication] openURL:settingsURL];
}}
I have also update my plist file with NSLocationAlwaysUsageDescription->String & NSLocationWhenInUseUsageDescription -> String.
Thank You.
1) check that you actually have a valid WiFi and 3G connection
if you do then
2) go to settings and reset your location services
3) then reset your network settings

didRangeBeacons not getting uuid in ios

I used the following code to get message from a particular beacon but it always shows null in uuid. When i run this code the "viewdidLoad method works fine but when it comes to didRangebeacons it shows only the last uuid beacons. Actually i want to check that Is beacon available for particular uuid and receive that signals and keep on checking for uuids in array and when it receives another signal it should display that beacon signal also.
- (void)viewDidLoad
{
[super viewDidLoad];
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
NSLog(#"Before assigning UUID");
NSArray *uuidArr = [NSArray arrayWithObjects: #"9146947B-441D-4116-B60E-4DD4659825AB", #"9146947B-441D-4116-B60E-4DD46598257C", #"9146947B-441D-4116-B60E-4DD46598257B", nil];
for(int i=0; i<[uuidArr count]; i++)
{
NSString *uuidTemp = [uuidArr objectAtIndex:i];
NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:uuidTemp];
self.myBeaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid
identifier:#"com.gimbal.iosexample"];
[self.locationManager startMonitoringForRegion:self.myBeaconRegion];
[self.locationManager startRangingBeaconsInRegion:self.myBeaconRegion];
if (![CLLocationManager isMonitoringAvailableForClass:[CLBeaconRegion class]])
{
NSString *msg = [NSString stringWithFormat:#"Monitoring not available for %#", uuidTemp];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Monitoring not available" message:msg delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles: nil];
[alert show]; return;
}
}
}
-(void)locationManager:(CLLocationManager*)manager didRangeBeacons:(NSArray*)beacons inRegion:(CLBeaconRegion*)region
{
NSLog(#"iBeacons found");
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Successfully found" message:nil delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles: nil];
[alert show];
self.statusLabel.text = #"iBeacon found!";
CLBeacon *foundBeacon = [beacons firstObject];
NSString *uuid = foundBeacon.proximityUUID.UUIDString;
NSString *major = [NSString stringWithFormat:#"%#", foundBeacon.major];
NSString *minor = [NSString stringWithFormat:#"%#", foundBeacon.minor];
NSLog(#"UUID: %#", uuid);
}
#end
Can anyone help me to do this.
Thanks in advance.
You are creating different beacon regions in your for loop, but your region identifier is the same, so the second region definition will replace the first, and then the second will be replaced by the third. You need to use a unique region identifier - something like
CLBeaconRegion *beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid
identifier:[NSString stringWithFormat:#"com.gimbal.iosexample.%d",i]];

Pin Annotation with UIAlertView

I created a button in a "bottom bar." When the user presses the button, I am trying to show a UIAlertView, so the user can enter an address which will result in a blue pin being shown on the map. This pin should then be saved to NSUserDefaults, so that the location is saved each time the app is restarted.
Here is what I have so far. The user can enter the address in the UIAlertView, but nothing happens...
- (IBAction)selectHq:(UIBarButtonItem *)sender
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Select Headquarters"
message:#"Enter Address"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Ok", nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
[[alert textFieldAtIndex:0] setKeyboardType:UIKeyboardTypeNumbersAndPunctuation];
[alert show];
UITextField *field = [alert textFieldAtIndex:0];
field.placeholder = #"Enter HQ Address";
if (!self.geocoder)
{
self.geocoder = [[CLGeocoder alloc] init];
}
NSString *hqAddress = [NSString stringWithFormat:#"%#", field.text];
[self.geocoder geocodeAddressString:hqAddress completionHandler:^(NSArray *placemarks, NSError *error) {
if ([placemarks count] > 0)
{
CLPlacemark *placemark = [placemarks objectAtIndex:0];
CLLocation *location = placemark.location;
CLLocationCoordinate2D hqCoordinate = location.coordinate;
NSLog (#"%f %f", hqCoordinate.latitude, hqCoordinate.longitude);
MKCoordinateRegion region;
MKCoordinateSpan span;
span.latitudeDelta = 0.01;
span.longitudeDelta = 0.01;
region.span = span;
region.center = hqCoordinate;
MKPointAnnotation *hqAnnotation = [[MKPointAnnotation alloc] init];
[hqAnnotation setCoordinate:hqCoordinate];
[hqAnnotation setTitle:#"HQ"];
[[self mapView] addAnnotation:hqAnnotation];
[self.mapView setRegion:region animated:TRUE];
[self.mapView regionThatFits:region];
}
}];
[[NSUserDefaults standardUserDefaults] setObject:field.text forKey:HQ_KEY];
[[NSUserDefaults standardUserDefaults] synchronize];
You should implement the UIAlertViewDelegate and put your action code for alert button selection in to the delegate method.
- (IBAction)selectHq:(UIBarButtonItem *)sender
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Select Headquarters"
message:#"Enter Address"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Ok", nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
[[alert textFieldAtIndex:0] setKeyboardType:UIKeyboardTypeNumbersAndPunctuation];
[alert show];
[alert release] // if non-arc project.
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
// add your code here for tagging the map
// saving to nsuserdefaults.
}

Why is my core data saving slow?

Every time I try to save my NSManagedObjectContex, it takes 1-8 seconds each time. Here is my code:
- (IBAction)save
{
if (self.managedObjectContext == nil) {
self.managedObjectContext = [(RootAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
}
if (self.brandText.text.length == 0 || self.modelText.text.length == 0) {
UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:#"Error" message:#"Please fill out the required fields" delegate:self cancelButtonTitle:#"Dismiss" otherButtonTitles:nil, nil];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(125, 40, 31, 7)];
NSString *path = [[NSString alloc] initWithString:[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"bullet.png"]];
UIImage *bkgImg = [[UIImage alloc] initWithContentsOfFile:path];
[imageView setImage:bkgImg];
[alertView addSubview:imageView];
[alertView show];
} else {
Hand *a = [NSEntityDescription insertNewObjectForEntityForName:#"Hand" inManagedObjectContext:self.managedObjectContext];
a.brand = self.brandText.text;
a.caliber = self.cText.text;
self.managedObjectContext = self.app.managedObjectContext;
a.notes = self.notesView.text;
a.serialNumber = self.serialNumberText.text;
a.nickname = self.nicknameText.text;
a.model = self.modelText.text;
a.gunImage = self.image.image;
a.roundsFired = [NSString stringWithFormat:#"0"];
a.cleanRounds = [NSString stringWithFormat:#"500"];
a.showBadge = [NSNumber numberWithBool:YES];
[self dismissViewControllerAnimated:YES completion:nil];
NSError *error;
if (![self.managedObjectContext save:&error]) {
UIAlertView *errorAlert = [[UIAlertView alloc]initWithTitle:#"Error" message:#"There was an internal error. \n Please restart the app and try again, Thank You" delegate:self cancelButtonTitle:#"Dismiss" otherButtonTitles:nil, nil];
[errorAlert show];
}
}
}
The code just saves the all of the textFields text. What is the reason its so slow? Any help is greatly appreciated.
Based on your question is quite difficult to understand what is going on but I would modify the else statement as follows...
else {
Hand *a = [NSEntityDescription insertNewObjectForEntityForName:#"Hand" inManagedObjectContext:self.managedObjectContext];
a.brand = self.brandText.text;
a.caliber = self.cText.text;
// why this?
// self.managedObjectContext = self.app.managedObjectContext;
a.notes = self.notesView.text;
a.serialNumber = self.serialNumberText.text;
a.nickname = self.nicknameText.text;
a.model = self.modelText.text;
a.gunImage = self.image.image;
a.roundsFired = [NSString stringWithFormat:#"0"];
a.cleanRounds = [NSString stringWithFormat:#"500"];
a.showBadge = [NSNumber numberWithBool:YES];
NSError *error;
if (![self.managedObjectContext save:&error]) { // error during saving
UIAlertView *errorAlert = [[UIAlertView alloc]initWithTitle:#"Error" message:#"There was an internal error. \n Please restart the app and try again, Thank You" delegate:self cancelButtonTitle:#"Dismiss" otherButtonTitles:nil, nil];
[errorAlert show];
} else { // the save completes correctly, dismiss the view controller
[self dismissViewControllerAnimated:YES completion:nil];
}
}
If you want to monitor Core Data you should do it through Instrument. In addition you could set up Xcode as follows: XCode4 and Core Data: How to enable SQL Debugging.
Edit
Since the slow saving is due (based on your comment) to images, you should relies on these rules.
Core Data - Storing Images (iPhone)
Edit 2
Ok, since you don't know in advance about the size (in bytes) of your image, I really suggest to store the image in the filesystem and not in the Core Data store. In the db save only the path to your image. The image will be saved in background. This to prevent the UI to block.
Otherwise, if iOS 5 is the minimum requirement, use the External Storage flag.
How to enable External Storage for Binary Data in Core Data
Hope that helps.

Resources