I have a method in my appDelegate which gets latitude and longitude and returns a string which I can use in any viewController.
AppDelegate :
-(void)StartUpdating
{
locManager = [[CLLocationManager alloc] init];
locManager.delegate = self;
locManager.distanceFilter = kCLDistanceFilterNone; // whenever we move
locManager.desiredAccuracy = kCLLocationAccuracyHundredMeters; // 100 m
[locManager startUpdatingLocation];
}
#pragma mark
#pragma mark locationManager delegate methods
- (void)locationManager: (CLLocationManager *)manager
didUpdateToLocation: (CLLocation *)newLocation
fromLocation: (CLLocation *)oldLocation
{
float latitude = newLocation.coordinate.latitude;
strLatitude = [NSString stringWithFormat:#"%f",latitude];
float longitude = newLocation.coordinate.longitude;
strLongitude = [NSString stringWithFormat:#"%f", longitude];
//[self returnLatLongString:strLatitude:strLongitude];
}
-(NSString*)returnLatLongString
{
NSString *str = #"lat=";
str = [str stringByAppendingString:strLatitude];
str = [str stringByAppendingString:#"&long="];
str = [str stringByAppendingString:strLongitude];
return str;
}
I am calling StartUpdating in start of application. Now in my viewController I call this method:
AppDelegate *appDelegate=[AppDelegate sharedAppDelegate];
NSString *str = [appDelegate returnLatLongString];
But I get a crash in
str = [str stringByAppendingString:strLatitude];
in returnLatLongString.
I know I am getting crash because there is no value in strLatitude at that time. But how can I fix this? How can I still have updated value of latitude and longitude?
Also, I don't want to use locationManager in viewControllers. So that I can get current location in all viewControllers, I did it in appDelegate.
The crash might be because str is an NSString, and so therefore is not mutable. Assigning it back to itself in this case is problematic. It would be simpler just to use stringWithFormat:
NSString *str = [NSString stringWithFormat: #"lat=%#&long=%#", strLatitude, strLongitude];
Import your AppDelegate.h file. Then
Use the following code:
MyAppDelegate *myAppDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
NSString *result = [myAppDelegate returnLatLongString];
i think you need to init those variables (strLatitude, strLongitude) in your
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions method. if it hits this point at first time, they are not initialized so you get crash.
There are two potential problems in your code.
First of all make sure you declare strLatitude and strLongitude as strong properties in your header file:
#property (nonatomic, strong) NSString * strLatitude;
#property (nonatomic, strong) NSString * strLongitude;
Use #synthesize to automatically generate the proper getter and setter for them and assign the proper values to them as:
float latitude = newLocation.coordinate.latitude;
self.strLatitude = [NSString stringWithFormat:#"%f",latitude];
float longitude = newLocation.coordinate.longitude;
self.strLongitude = [NSString stringWithFormat:#"%f", longitude];
to make sure that they don't get released after they are assigned a value, because [NSString stringWithFormat:] returns autoreleased objects.
Secondly, after [locManager startUpdatingLocation]; it's going to take sometime before the system delivers the first location update. Therefore you need to check if the strLatitude and strLongitude have already been assigned values before you try to construct another string with them. Something similar to this should do the job:
-(NSString*)returnLatLongString
{
if (self.strLatitude == nil || self.strLongitude == nil)
return nil;
NSString *str = #"lat=";
str = [str stringByAppendingString:strLatitude];
str = [str stringByAppendingString:#"&long="];
str = [str stringByAppendingString:strLongitude];
return str;
}
Then of course the view controllers who are going to use [AppDelegate returnLatLongString] need to check that the returned value is not nil.
Hope this helps...
You are doing a mistake with creating a object of AppDelegate Class..
To create object just write this code :
AppDelegate *appDelegate=(AppDelegate *)[[UIApplication sharedApplication] delegate];
NSString *str = [appDelegate returnLatLongString];
Its done..
Related
i have 2 classes in my app. View1 & View2;
i want to use an object like array, strin, label.text in another class
when i used them the shows null ;
View1.h:
{
NSMutableArray *array;
IBOutlet UILabel *lbl;
NSString *str;
}
#property(nonatomic,retain) NSMutableArray *array;
#property(nonatomic,retain)IBOutlet UILabel *lbl;
#property(nonatomic,retain) NSString *str;
#end;
View1.m
#synthesize array;
#synthesize lbl;
#synthesize str;
array = (1,2,3,..., nil) some dataa
str = #"HAI";
lbl.text = #"Text in label aaaa";
NSLog( #" %#", array );
NSLog( #" %#", lbl.text );
NSLog( #" %#", str );
gives correct out put
but in
View2:
#implementation View2
#import "View1"
.
..
....
View1 *one = [View1 alloc]initwit.....................];
NSLog( #" %#", one.array );
NSLog( #" %#", one.lbl.text );
NSLog( #" %#", one.str );
prints null value
why ? what to do?
thanks in advance..
Very easy. You can allocate this array in your AppDelegate, and then call it from your UIViews. Or you can allocate it in one of your UIViews and set point to this array into AppDelegate.
Example:
//UIView 1
NSArray *array = [[NSArray alloc] init];
MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
appDelegate.mySharedArray = array;
//UIView2
MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
NSArray *array = appDelegate.mySharedArray;
Thats it
Are you sure you give initial values to the variables from view1?
please make sure the init method for view1 gives some values to the argument, i.e. in
initwit..............
make sure you have:.
array = (1,2,3,..., nil) some dataa
str = #"HAI";
lbl.text = #"Text in label aaaa";
by the way, it is wrong code to initialize array the way you did, you should use one of NSArray initialize methods.
In my application I have location function:
- (void)locationUpdate:(CLLocation *)location {
lati = [[NSString alloc]initWithFormat:#"%f", location.coordinate.latitude] ;
longi = [[NSString alloc ]initWithFormat:#"%f", location.coordinate.longitude ];
[self ParseXML_of_Google_PlacesAPI:googleUrl];
}
...and I have another function to which I want to pass lati and longi:
-(void)ParseXML_of_Google_PlacesAPI:(NSString *)_googleUrl {
//use lati and longi in this line
googleUrl=[NSString stringWithFormat:#"https://maps.googleapis.com/maps/api/place/search/xml?location=%f,%f&radius=500&name=asda&sensor=false&key=mykey",lati,longi];
NSURL *googlePlacesURL = [NSURL URLWithString:googleUrl ];
NSData *xmlData = [NSData dataWithContentsOfURL:googlePlacesURL];
xmlDocument = [[GDataXMLDocument alloc]initWithData:xmlData options:0 error:nil];
NSArray *arr = [xmlDocument.rootElement elementsForName:#"result"];
placesOutputArray=[[NSMutableArray alloc]init];
for(GDataXMLElement *e in arr ){
[placesOutputArray addObject:e];
}
}
How can I do that? I just need the values of lati and longi in the ParseXML_of_Googe_PlacesApi: method. Everything else is working fine
Change your declaration to:
-(void)ParseXML_of_Google_PlacesAPI:(NSString *)_googleUrl withLat:(NSString*)lati andLong:(NSString*)longi {
Then change your calling code:
[self ParseXML_of_Google_PlacesAPI:googleUrl withLat:lati andLong:longi];
You need to modify the ParseXML_of_Google_PlacesAPI:(NSString *)_googleUrl method to take other arguments:
i.e )ParseXML_of_Google_PlacesAPI:(NSString *)_googleUrl long:(float) longitude lat:(float) latitude
You can use float if they floats or replace the float with NSString if they are nsstrings like in your method.
You can then use the nsstringformat to reformat your URL.
Rewrite your method as
- (void)parseXMLOfGooglePlacesAPI:(NSString *)url latitude:(NSString *)latitude longitude:(NSString *)longitude;
and then call it as
[self parseXMLOfGooglePlacesAPI:googleURL latitude:late longitude:longi];
If you don't want to rewrite the method or you need to use the variables in more than one method, make lati and longi properties of the class this code appears in.
In the .h file you would define:
#property(nonAtomic, retain) NSString *lati;
#property(nonAtomic, retain) NSString *longi;
.. and in the .m file you would:
#synthesize lati, longi;
Then you would use them like:
- (void)locationUpdate:(CLLocation *)location {
self.lati = [[NSString alloc]initWithFormat:#"%f", location.coordinate.latitude] ;
self.longi = [[NSString alloc ]initWithFormat:#"%f", location.coordinate.longitude ];
[self ParseXML_of_Google_PlacesAPI:googleUrl];
}
... and:
-(void)ParseXML_of_Google_PlacesAPI:(NSString *)_googleUrl {
googleUrl=[NSString stringWithFormat:#"https://maps.googleapis.com/maps/api/place/search/xml?location=%f,%f&radius=500&name=asda&sensor=false&key=mykey",self.lati,self.longi];
NSURL *googlePlacesURL = [NSURL URLWithString:googleUrl ];
NSData *xmlData = [NSData dataWithContentsOfURL:googlePlacesURL];
xmlDocument = [[GDataXMLDocument alloc]initWithData:xmlData options:0 error:nil];
NSArray *arr = [xmlDocument.rootElement elementsForName:#"result"];
placesOutputArray=[[NSMutableArray alloc]init];
for(GDataXMLElement *e in arr ){
[placesOutputArray addObject:e];
}
}
I have this functions:
- (NSMutableDictionary *) getUserDataDictionary
{
[userDataDicionary removeAllObjects];
userDataDicionary = [[NSMutableDictionary alloc] initWithContentsOfFile:[self getUserDataDictionaryPath]];
return userDataDicionary;
}
- (int) getIndexOfLastVehicle
{
MyAppDelegate *app = (MyAppDelegate*)[[UIApplication sharedApplication] delegate];
NSMutableDictionary *tmpUserData = [app getUserDataDictionary];
int lastHighestIndex = -1;
for(id item in [tmpUserData allKeys]){
NSString *keyInArray = (NSString *)item;
if ([keyInArray rangeOfString:#"VEHICLE-"].location != NSNotFound) {
//f.e. "VEHICLE", "1", "TYPE"...or "VEHICLE", "1", "SPZ"...or "VEHICLE", "2", "TYPE" etc
NSArray * separatedComponents = [keyInArray componentsSeparatedByString:#"-"];
int indexOfVehicle = [(NSString *)[separatedComponents objectAtIndex:1] intValue];
if(indexOfVehicle > lastHighestIndex){
lastHighestIndex = indexOfVehicle;
}
}
}
return lastHighestIndex;
}
The problem is:
after this code:
MyAppDelegate *app = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
NSMutableDictionary *tmpUserData = [app getUserDataDictionary];
int lastVehicleIndex = [self getIndexOfLastVehicle];
The tmpUserData is EMPTY.
But when I changed order to this:
int lastVehicleIndex = [self getIndexOfLastVehicle];
MyAppDelegate *app = (MyAppDelegate*)[[UIApplication sharedApplication] delegate];
NSMutableDictionary *tmpUserData = [app getUserDataDictionary];
The tmpUserData is correctly filled.
Can someone explain this behavior?
Thanks
One of you problems lies in the method getUserDataDictionary. You are calling removeAllObjects which does not releases the userDataDictionary. You have to release it instead of removingAllObject. The actual release will release all it's objects for you.
I'm far from being a pro in Objective C, but the other I had a similar problem with az NSMutableArray. The problem in my case was that something got released or inited one more time than required.
I suggest putting a few NSLog()-s here and there to find out where your content goes lost. I did this, I basically put an NSLog to each and every instruction involving my object, and finally I was able to fix the stuff.
Just an idea, probably it helps.
You have problem in this method:
- (NSMutableDictionary *) getUserDataDictionary
{
[userDataDicionary release];
userDataDicionary = [[NSMutableDictionary alloc] initWithContentsOfFile:[self getUserDataDictionaryPath]];
return userDataDicionary;
}
I have written the following code to find the current location.
It works well and prints the current location when I print lat2 and logg2 below in NSLOg, but it is not assigning value to lables. When I print label the value is null.
And I want to access lat2 and logg2 values outside the method didUpdateToLocation.
I am not able to access these values outside the didUpdateToLocation method even though
I have declared logg2 and lat2 globally. Outside this method it gives null value. How can I do that? What is problem here? Is there any sample code or tutorial fot that?
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization.
}
return self;
}
-(void)awakeFromNib {
[self update];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
if (wasFound) return;
wasFound = YES;
CLLocationCoordinate2D loc = [newLocation coordinate];
lat2 = [NSString stringWithFormat: #"%f", loc.latitude];
logg2= [NSString stringWithFormat: #"%f", loc.longitude];
NSLog(#"latitude is %#",lat2);
NSLog(#"longitude is %#",logg2);
NSLog(#"*******This is the login view controller did update locationmethod of loginview controller.");
NSLog(#"latitude is %f",[lat2 floatValue]);
NSLog(#"longitude is %f",[logg2 floatValue]);
labellat.text = [NSString stringWithFormat: #"%f", loc.latitude];
labellog.text= [NSString stringWithFormat: #"%f", loc.longitude];
//NSLog(#"text of label is %#",labellat.text);
//NSLog(#"text of label is %#",labellog.text);
//lat=loc.latitude;
//log=loc.longitude;
//altitude.text = [NSString stringWithFormat: #"%f", newLocation.altitude];
// NSString *mapUrl = [NSString stringWithFormat: #"http://maps.google.com/maps?q=%f,%f", loc.latitude, loc.longitude];
// NSURL *url = [NSURL URLWithString:mapUrl];
// [[UIApplication sharedApplication] openURL:url];
}
- (IBAction)update {
locmanager = [[CLLocationManager alloc] init];
[locmanager setDelegate:self];
[locmanager setDesiredAccuracy:kCLLocationAccuracyBest];
NSLog(#"*********This is the location update method of login view controller.");
[locmanager startUpdatingLocation];
}
Basic memory management:
lat2 = [NSString stringWithFormat: #"%f", loc.latitude];
logg2= [NSString stringWithFormat: #"%f", loc.longitude];
These strings are destroyed (deallocated) almost right after you create them. Read up on memory management guidelines. Don't use globals either. If you must, this should fix your strings disappearing:
[lat2 release];
[logg2 release];
lat2 = [[NSString stringWithFormat: #"%f", loc.latitude] retain]; // keep string alive until we release it
logg2= [[NSString stringWithFormat: #"%f", loc.longitude] retain];
Oh, and did you remember to connect the outlets to your labels in Interface Builder?
Use this to show your latitude and longitude in labels.
labellat.text = [NSString stringWithFormat: #"%.6f", loc.latitude];
labellog.text= [NSString stringWithFormat: #"%.6f", loc.longitude];
Please retain the location coordinate to get the values if you want call this from any other places, otherwise it may autorelase.
You can make use of
labellat.text = [NSString stringWithFormat: #"%#", lat2];
labellog.text= [NSString stringWithFormat: #"%#", logg2];
But I think it's better to store the latitude and longitude values as a float itself in an instance variable and thereby getting access to it easily. If you want to show it in a label, use the method stringWithFormat: just as you did.
UPDATE:
The tutorial Hello There: A CoreLocation Tutorial may help you.
I keep getting a memory leak indication from this sql statement when I assign the value retrieved from the database...
Person *tmpPerson = [[Person alloc] init];
tmpPerson.personName = [NSString stringWithUTF8String: (char*)sqlite3_column_text(SelectPersonStmt, 0)];
tmpPerson.personEmail = [NSString stringWithUTF8String: (char*)sqlite3_column_text(SelectPersonStmt, 1)];
[personList addObject:tmpPerson];
[tmpPerson release];
However if i replace the nsobject class object ...tmpPerson with regular NSString's ...leaks doesn't complain anymore? Does anyone know why?
NSString * personName = [NSString stringWithUTF8String:(char*)sqlite3_column_text(SelectPersonStmt, 0)];
NSString * personEmail = [NSString stringWithUTF8String:(char*)sqlite3_column_text(SelectPersonStmt, 1)];
Here is my class definition ... is there anything wrong with it?
#interface Person : NSObject {
NSString* personName;
NSString* personMobile;
NSString* personEmail;
}
#property (nonatomic, retain) NSString* personName, *personEmail, *personMobile;
- (id)init
{
if ((self = [super init])) {
personName = [NSString string];
personEmail = [NSString string];
personMobile = [NSString string];
}
return self;
}
Am I missing something here ? Should I be even initializing these strings, it didn't seem to make any difference? I put them there incase i wanted to initialize them with some default value.
While testing this through instruments, i noticed that the memory leak is triggered during the deallocation method. I tried this and it didn't help either
-(void) dealloc
{
personName = nil;
personEmail = nil;
[super dealloc];
}
Any help would be greatly appreciated. I've seen a lot of posts related to this but I'm not sure if folks are getting the same behavior I have mentioned.
You have to release your ivar in the dealloc:
-(void) dealloc
{
[personName release];
[personEmail release];
[personMobile release];
personName = nil; // Optionnal
personEmail = nil; // Optionnal
personMobile = nil; // Optionnal
[super dealloc];
}
You should release the used strings in the Person struct, not setting it to NULL.
Once you set it to NULL and there are no other objects referring to it, you have a leak, the system does not know how to reclaim it.
EDIT: damn, my answer came 10 seconds late :P