EXC_BAD_ACCESS issue on iphone and simulator - iphone

I am getting an EXC_BAD_ACCESS out side of my own code. Currently my code gets a URL through a shareURLCache object and then starts url connection. Once I leave the method that starts the url connection I hit the EXC_BAD_ACCESS. I have tried using instruments to find any zombies and I have analysed for memory leaks and not turned up either. At this point I am completely stuck.
Here is the code that loads the url and starts the url connection
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
NSLog(#"At new location: %#",newLocation);
MKCoordinateRegion region =
MKCoordinateRegionMakeWithDistance([newLocation coordinate], 750, 750);
[mapView setRegion:region animated:YES];
[location stopUpdatingLocation];
CLLocationCoordinate2D coord = [newLocation coordinate];
NSURL *url = [urlCache getReccomendationForUID:#"12345" atLat:coord.latitude
atLon:coord.longitude forCategories:nil];
// Create the request.
NSURLRequest *request = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
// create the connection with the request
// and start loading the data
connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
if (connection) {
// Create the NSMutableData to hold the received data.
// xmlData is an instance variable declared elsewhere.
xmlData = [[NSMutableData alloc]init];
} else {
NSLog(#"Could not create connection");
}
}
Method from the sharedURLCache that returns the url
-(NSURL *)getReccomendationForUID:(NSString *)u atLat:(double)lat atLon:(double)lon forCategories:(NSArray *)cat
{
if(remote) {
NSMutableString *categories = [[NSMutableString alloc]init];
for(NSString *s in cat) {
[categories appendString:#"&cat="];
[categories appendString:s];
}
NSString *s = [NSString stringWithFormat:#"%#/recommendation?uid=%#&psw=null&lat=%f&lon=%f?%#",
apiRoot,u,lat,lon,categories];
[categories release];
return [NSURL URLWithString:s];
} else {
return [[NSBundle mainBundle] URLForResource:#"XMLTest" withExtension:#"xml"];;
}
}

Just start by commenting out code and running to see if you can get the mem error to disappear then start adding code again until it appears, then you have a better idea where the issue is. it could be anywhere in your code since you seem to have a number of objects in there that are not passed in e.g. 'location'.
[location stopUpdatingLocation];

I had same memory issue with
[mapView setRegion:region animated:YES];
This method doesn't like fast updates...

Related

CLGeocoder not working

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after app launch
[window addSubview:viewController.view];
[window makeKeyAndVisible];
[window addViewForTouchPriority:viewController.view];
if(self.locationManager==nil){
locationManager=[[CLLocationManager alloc] init];
locationManager.delegate=self;
locationManager.purpose = #"We will try to tell you where you are if you get lost";
locationManager.desiredAccuracy=kCLLocationAccuracyBest;
locationManager.distanceFilter=500;
self.locationManager=locationManager;
}
geoCoder = [[CLGeocoder alloc] init];
if([CLLocationManager locationServicesEnabled]){
[self.locationManager startUpdatingLocation];
}
return YES;
}
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
lati = [[NSString alloc] initWithFormat:#"%+.6f", newLocation.coordinate.latitude];
NSLog(#"address:%#",lati);
longi = [[NSString alloc] initWithFormat:#"%+.6f", newLocation.coordinate.longitude];
NSLog(#"address:%#",longi);
CLLocationCoordinate2D coord;
coord.latitude = [lati doubleValue];
coord.longitude = [longi doubleValue];
[geoCoder reverseGeocodeLocation: newLocation completionHandler: ^(NSArray *placemarks, NSError *error)
{
//Get nearby address
CLPlacemark *placemark = [placemarks objectAtIndex:0];
//String to hold address
NSString *locatedAt = [[placemark.addressDictionary valueForKey:#"FormattedAddressLines"] componentsJoinedByString:#", "];
//Print the location to console
NSLog(#"I am currently at %#",locatedAt);
address = [[NSString alloc]initWithString:locatedAt];
NSLog(#"address:%#",address);
}];
}
I am using above code to get address by giving latitude and longitude, but control is not entering in to geocoder method, it skips it. Can anybody help me in it.
Thanks in advance.
It doesn't matter, control does not enter in the method, but it works, note the output it will work.
that is normal, because the code inside the reverseGeocodeLocation is execute inside a block.
The execution of the code inside a block occurs in another thread, so is not execute in the main thread, that's why the control don't enter inside the geocoder method.

nearby venue to iphone into simple array

Im really having a hard time figuring this out. Ive read a bunch of PDFS and stackoverflow questions on this but I have never used and API and can't quiet get it.
I am trying to get my longitude and latitude coordinates and use any API out there (foursquare, google maps, any others you can recommend that are free?) to get a list of nearby parks and just put it into an NSMutableDictionary key=name object=#"distance". No need to get all its content, just distance and name. But I have been stuck on the first part, getting my longitude and latitude coordinates for over 4 hours. Can anyone show me code wise how I would get my coordinates, no need to explain how to parse the API, once i have my coordinates I feel like I can figure that out. Ive downloaded apples locateme source code but still cant get it to work on mine. Is there maybe a set of easy to follow steps or code someone can provide that I can just use and get this headache over with? Ive imported the location framework. Is there a quick 10-20 lines of code to solve this, not 3 additional view controllers with so much I dont quiet understand.
Thanks a lot
- (void)viewDidLoad
{
[super viewDidLoad];
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone; // whenever we move
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters; // 100 m
[locationManager startUpdatingLocation];
}
#pragma mark Current location methods
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
latit = newLocation.coordinate.latitude;
longit = newLocation.coordinate.longitude;
NSLog(#"latitude = %f",latit);
NSLog(#"longitude = %f",longit);
[manager stopUpdatingLocation];
[self getNearByList];
}
-(void)getNearByList
{
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"yyyyMMdd"];
NSString *currentDate = [dateFormat stringFromDate:[NSDate date]];
[dateFormat release];
NSURL *url = [NSURL URLWithString:[[NSString stringWithFormat:#"https://api.foursquare.com/v2/venues/search?ll=%f,%f&client_id=YOUR_CLIENT_ID_HERE&client_secret=YOUR_CLIENT_SECRET_HERE&v=%#&limit=100&radius=2000&categoryId=4bf58dd8d48988d1e0931735,4bf58dd8d48988d176941735,4bf58dd8d48988d1ed941735,4bf58dd8d48988d119951735,4bf58dd8d48988d123941735,4d954afda243a5684865b473,4edd64a0c7ddd24ca188df1a,4bf58dd8d48988d1c9941735,4bf58dd8d48988d1bd941735,4bf58dd8d48988d124951735,4bf58dd8d48988d115951735,4bf58dd8d48988d11a951735,4bf58dd8d48988d10c951735,4bf58dd8d48988d11b951735,4bf58dd8d48988d11e951735,4bf58dd8d48988d1f9941735,4bf58dd8d48988d1f5941735,4bf58dd8d48988d113951735,4f04afc02fb6e1c99f3db0bc,4bf58dd8d48988d110951735,4bf58dd8d48988d1f2941735,4bf58dd8d48988d1fd941735,4bf58dd8d48988d103951735,4bf58dd8d48988d104941735,4f04aa0c2fb6e1c99f3db0b8,4d1cf8421a97d635ce361c31,4bf58dd8d48988d1f8941735,4d4b7105d754a06374d81259,4bf58dd8d48988d16d941735,4bf58dd8d48988d128941735,4bf58dd8d48988d111951735,4bf58dd8d48988d1ca941735,4bf58dd8d48988d117951735,4bf58dd8d48988d107951735,4bf58dd8d48988d1fa941735,4bf58dd8d48988d118951735,4bf58dd8d48988d17f941735,4bf58dd8d48988d1ac941735,4bf58dd8d48988d180941735",latit,longit,currentDate] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; //YOU CAN FOUND MORE CATEGORY ID AT FOURSQURE WEBSITE..
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url cachePolicy: NSURLRequestReloadIgnoringCacheData timeoutInterval: 30.f];
NSLog(#"url = %#",urlRequest);
webData1 = [[NSMutableData data] retain];
urlConnection = [[NSURLConnection alloc] initWithRequest: urlRequest delegate: self];
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[webData1 setLength: 0];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[webData1 appendData:data];
//NSLog(#"webData1 = %#",webData1);
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
UIAlertView *alert1 = [[UIAlertView alloc] initWithTitle:#"Error"
message : #"An error has occured."
delegate:nil
cancelButtonTitle :#"OK"
otherButtonTitles :nil];
[alert1 show];
[alert1 release];
[webData1 release];
[connection release];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSString *data = [[NSString alloc] initWithBytes: [webData1 mutableBytes] length:[webData1 length] encoding:NSUTF8StringEncoding];
NSLog(#"data = %#",data);
[connection release];
[webData1 release];
}
Use Google Place Api.You just need to register and than you will get key for api
//example api. This api will give you food in your defined radius of longitude and latitude in the json data format
https://maps.googleapis.com/maps/api/place/search/json?location=-33.8670522,151.1957362&radius=500&types=food&name=harbour&sensor=false&key=AddYourOwnKeyHere
Google Place API
Hope, this will help you..enjoy...

Memory leak using location manager

I use the location manager with "didUpdateToLocation". I have a memory leak that I cannot explain:
- (void) locationManager:(CLLocationManager *) manager didUpdateToLocation:(CLLocation *) newLocation
fromLocation:(CLLocation *) oldLocation {
[newLocation retain];
NSString *lCoordinates = [[NSString alloc] initWithFormat:#"%f,%f",newLocation.coordinate.latitude,newLocation.coordinate.longitude];//Memory leak here!!!
[self setLocationCoordinates:lCoordinates];
[lCoordinates release];
NSString *lat = [[NSString alloc] initWithFormat:#"%f,%f", newLocation.coordinate.latitude,newLocation.coordinate.longitude];
[lm stopUpdatingLocation];
NSMutableString *s = [[NSMutableString alloc]initWithFormat:#"https://maps.googleapis.com/maps/api/place/search/json?location=%#&radius=10&sensor=true&key=---MyKey---", lat];
NSLog(s);
id delegate = self;
AsyncConnectionController * connectionController = [[[AsyncConnectionController alloc] initWithDelegate:delegate
selSucceeded:#selector(currentLocationConnectionSucceeded:)
selFailed:#selector(currentLocationconnectionFailed:)] autorelease];
NSURL *url = [[NSURL alloc] initWithString:s];
[connectionController startRequestForURL:url];
[lat release];
[s release];
[url release];
[newLocation release];
}
Thanks all for your help!!!
You should be able to reduce your code substantially just by using convenience methods (makes it more readable as well):
- (void) locationManager:(CLLocationManager *) manager didUpdateToLocation:(CLLocation *) newLocation fromLocation:(CLLocation *) oldLocation {
NSString *lCoordinates = [NSString stringWithFormat:#"%f,%f",newLocation.coordinate.latitude,newLocation.coordinate.longitude];
[self setLocationCoordinates:lCoordinates];
NSString *lat = [NSString stringWithFormat:#"%f,%f", newLocation.coordinate.latitude,newLocation.coordinate.longitude];
[lm stopUpdatingLocation];
NSString *s = [NSString stringWithFormat:#"https://maps.googleapis.com/maps/api/place/search/json?location=%#&radius=10&sensor=true&key=---MyKey---", lat];
NSLog(s);
AsyncConnectionController * connectionController = [[[AsyncConnectionController alloc] initWithDelegate:self
selSucceeded:#selector(currentLocationConnectionSucceeded:)
selFailed:#selector(currentLocationconnectionFailed:)] autorelease];
NSURL *url = [NSURL urlWithString:s];
[connectionController startRequestForURL:url];
}
OP specifies that connectionController is autorelease.

How to retrieve current city name using wifi/3g ip address with iPhone/iOS programming (Objective-c)?

I want to retrieve the current "city name" of the iPhone using ip address of device (wifi/3g). Is there any way to do it? please help me out.
Following is the place where I want the current location.
-(BOOL)fetchAndParseRss{
NSString * CurrentLocation = <I want the retrieved Location here!!>;
NSString * URLrss = [NSString stringWithFormat:#"http://news.google.com/news?q=location:%#&output=rss", CurrentLocation];
NSURL *url = [NSURL URLWithString:URLrss];
NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:url];
}
Actually i am developing an app for myself that displays the news of current city.
You can use CLLocationManager and MKReverseGeocoder to get users city.
First add CLLocationManager and start updating user location
- (void)startLocationManager
{
if (locManager==nil)
locManager = [[CLLocationManager alloc] init];
if (locManager.locationServicesEnabled)
{
NSLog(#"User has opted out of service on it error");
} else {
locManager.delegate = self;
locManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
[locManager startUpdatingLocation];
}
}
Then add location manager delegate methods to use MKReverseGeocoder.
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
NSLog(#"Manager error: %#", [error description]);
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
self.geocoder = [[MKReverseGeocoder alloc] initWithCoordinate:newLocation.coordinate];
[geocoder release];
geocoder.delegate = self;
[geocoder start];
[manager stopUpdatingLocation];
}
and of course you have to implement MKReverseGeocoder Delegate methods
- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFailWithError:(NSError *)error
{
NSLog(#"reverseGeocoder:%# didFailWithError:%#", geocoder, error);
}
- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFindPlacemark:(MKPlacemark *)placemark
{
// with the placemark you can now retrieve the city name
NSString *city = [placemark.addressDictionary objectForKey:#"City"];
NSLog(#"City is %#", city);
}
This method can be use if user gives permission to your application for location manager.
One option would be to make an HTTP request to a website like geoiptool.com and scrape the city information from the response. I'm unsure how much success you'll have when using mobile phone networks, though—wifi worked when I tried it on my phone, but 3G didn't.

How to wait for location manager for the current location?

I am developing an iPhone application in which I want to show nearest restaurants based on the current location
For that In the applicationDidFinishLaunching I am doing this :
self.locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
NSURL *url = [[NSURL alloc] initWithString:#"http://192.168.0.150/server1/Service.asmx/nearest?lat1=23.013163&lon1=72.559068"];
NSMutableURLRequest* request2=[NSMutableURLRequest requestWithURL:url];
[request2 setHTTPMethod:#"GET"];
[request2 setTimeoutInterval:10];
NSURLResponse *response=nil;
NSError *err=nil;
NSData *data1=[[NSURLConnection sendSynchronousRequest:request2 returningResponse:&response error:&err] retain];
if(data1 == nil)
{
UIAlertView* alert = [[UIAlertView alloc]initWithTitle:#"Alert" message:#"The network is not available.\n Please check the Internet connection." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
[alert release];
}
else
{
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithData:data1];
//Initialize the delegate.
XMLParser *parser = [[XMLParser alloc] initXMLParser];
//Set delegate
[xmlParser setDelegate:parser];
//Start parsing the XML file.
#try {
BOOL success = [xmlParser parse];
if(success)
NSLog(#"No Errors");
else
NSLog(#"Error Error Error!!!");
}
#catch (NSException * e) {
NSLog(#"Exception in parsing %# %#",[e name], [e reason]);
}
}
The problem scenario.
the location manager start updating the location
The webservice gets executed before that so I can't get the location values .
I I am putting the web service call in the delegate method then the application launches before the web service gets executed.
in the delegate method I am setting the latitude and longitude in the appropriate strings.
The Problem is that how ensure that the service will not be called until the location manager updates that location and then pass the location to the web service and then call that web service ..
CLLocationManaged has the delegate method.
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
it will be called when CLLocationManager will receive some coordinates. Or
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
it will be called when locationManager cannot receive any coordinates. Or when user don't allow to find current location. Also you should call stopUpdatingLocation if you don't want to receive more accurate results.
So you can make your request inside delegate method to be sure is will be called only after updating current location.
One thing I'd recommend is to do your urlRequest in a thread instead as hinted Sixten Otto.
I would setup the locationManager in viewDidLoad or viewDidAppear like you have. Then there are two ways I would call the urlrequest:
Have the request be performed in didUpdateToLocation delegate, then you will know that your urlrequest will only execute after the location is found. This is the suggestion that Morion made.
The other way is to have a notification in the didUpdateToLocation delegate so that when the location is found, it notifies a function to perform the urlRequest.Look up this Tutorial for setting up notifications, it is very helpful and good to know for a lot of programs.
Also, as I mentioned before, you should perform an urlrequest in a thread. The reason is, your request could be locked up and your user would have no control to exit the request. To do this, Setup an NSOperation and place it in the NSOperationQueue:
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget: self
selector: #selector(METHOD:)
object: OBJECTorNIL;
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:operation];
for more threading info, look up this Tutorial