views:

214

answers:

2

I've got a problem with a NSString in my app.
I've defined it in the header file of my view controller.

    NSString *locationCoordinates;

and I set its value in a -(void) method.

- (void)locationUpdate:(CLLocation *)location {
    <...>

    NSArray *locArray = [locString componentsSeparatedByString:@", "];

    NSString *xCoordinate = [locArray objectAtIndex:0];
    NSString *yCoordinate = [locArray objectAtIndex:1]; 

    locationCoordinates = [NSString stringWithFormat:@"%@,%@", xCoordinate, yCoordinate];
}

In this method, I can print it to the console with

NSLog(locationCoordinates);

But if I want to view it in the console in another method, my app instantly quits.

- (IBAction)saveAndReturnToRootView {
    NSLog(locationCoordinates);
}

The console tells me:

2010-02-24 14:45:05.399 MyApp[73365:207] *** -[NSCFSet length]: unrecognized selector sent to instance 0x4c36490
2010-02-24 14:45:05.400 MyApp[73365:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSCFSet length]: unrecognized selector sent to instance 0x4c36490'
2010-02-24 14:45:05.401 MyApp[73365:207] Stack: (
  32887899,
  2434934025,
  33269819,
  32839286,
  32691906,
  32417461,
  32527181,
  32527085,
  32747749,
  356942,
  630491,
  63461,
  2868313,
  4782069,
  2868313,
  3275682,
  3284419,
  3279631,
  2973235,
  2881564,
  2908341,
  40984273,
  32672640,
  32668744,
  40978317,
  40978514,
  2912259,
  9744,
  9598
)

How can I solve this problem?

Thanks in advance ;-)

+5  A: 

You should retain the string when storing it in a variable of your class:

locationCoordinates = [NSString stringWithFormat:@"%@,%@", xCoordinate, yCoordinate];
[locationCoordinates retain];

The reason is that [NSString stringWithFormat:...] returns an autoreleased instance. The string will be automatically released when the function ends.

You could also copy the string:

locationCoordinates = 
    [[NSString stringWithFormat:@"%@,%@", xCoordinate, yCoordinate] copy];

And of course, don't forget to release it again in dealloc:

- (void) dealloc {
    [locationCoordinates release];

    [super dealloc];
}
Philippe Leybaert
If you are using this method and not a property, than you need to also send a release message to locationCoordinates before you assign it a new value, otherwise you will leak memory if locationUpdate: is called more than once.
Brandon Bodnár
That works, thank you very much!
Yassin
+7  A: 

You arent retaining the String, so the memory is being cleared up. This causes the crash when you try to access it.

To retain it, you can add the following line

[locationCoordinates retain];

Remember to release it when you no longer need it - probably in the destructor of your class, or else you will have a memory leak.


It is standard practice in Objective C to use properties for such class members. In the header file use

@property (nonatomic, retain) NSString *locationCoordinates;

Then in the implementation chuck in a

@synthesize locationCoordinates;

When you access locationCoordinates access it through self as :

self.locationCoordinates = [NSString stringWithFormat:@"%@,%@", xCoordinate, yCoordinate];

Objective C will create a getter and setter property that will handle the retain for you in the most efficient manner.

Incidentally, the nonatomic keyword in the property tells objective c that you dont need it to create any thread synchronization around the property access. If you are going to be multithreading the class, you should consider removing nonatomic. This will then ensure the property access is thread safe.

No point doing any work that you can get the compiler to do for you!

Mongus Pong
+1 for @property
willcodejavaforfood
Okay, great, thank you!
Yassin
Awesome, pleasure to help! Ive finally managed to get my head around Objective C memory management enough to be able to answer a question about it. Its been a long journey..! ;-)
Mongus Pong