2

I'm developing an iOS application with latest SDK and XCode.

This is a simple question but I don't know how to do it because I don't want any memory leaks on my code.

I'm using ARC on my project and I have the following header declaration:

@interface UserPreferences : NSObject
{
    NSUserDefaults* prefs;
}

@property (nonatomic, readonly) NSString* appLanguage;

// More code

- (void) setAppLanguage:(NSString *)appLanguage;

// More code
@end

And this is how I've implemented - (void) setAppLanguage:(NSString *)appLanguage;.

- (void) setAppLanguage:(NSString *)newAppLanguage
{
    [prefs setObject:appLanguage forKey:APP_LANGUAGE_KEY];
    appLanguage = [NSString stringWithString:newAppLanguage];
}

Is appLanguage = [NSString stringWithString:newAppLanguage]; correct?

I don't know it appLanguage will have a value when I set a new one to it.

Is my code correct?

VansFannel
  • 45,055
  • 107
  • 359
  • 626
  • 2
    If appLanguage is NSString and newAppLanguage is also NSString you dont need to do stringWithString:, you can just equate the two.appLanguage=newAppLanguage; – Divya Dec 10 '12 at 12:32
  • `appLanguage will have a value when I set a new one to it.` yes it will have, and new value will replace its previous value. You can simply write `@property (strong) NSString* appLanguage;` and your setAppLanguage to override the default setter. no need to make one readonly and then creating confusion my making it writ+read. – Anoop Vaidya Dec 10 '12 at 12:42

2 Answers2

1

Your code doesn't have any leaks; ARC automatically releases the previous value for appLanguage for you. I would write appLanguage = [newAppLanguage copy] rather than using stringWithString:, but the effect is the same.

Jesse Rusak
  • 56,530
  • 12
  • 101
  • 102
  • Why would you bother copying an immutable NSString? – J Shapiro Dec 10 '12 at 13:29
  • @JShapiro The problem is that ```newAppLanguage``` could be an NSMutableString (since it's a subclass of NSString), and so it could be mutated surprisingly unless you copy it first. (This is why Apple usually declares NSString, NSArray and similar objects as copy properties.) – Jesse Rusak Dec 10 '12 at 14:28
0

Unless you've omitted some code, this won't work...

You've created an instance variable for NSUserDefaults, but have never instantiated it with a value. When you call [prefs setObject:appLanguage forKey:APP_LANGUAGE_KEY]; prefs will be nil.

At some point, before you use prefs, you need to do something like: prefs = [NSUserDefaults standardUserDefaults];

If you have instantiated prefs somewhere else, you'll still have an issue with this logic. Presumably, you're trying to change the NSUserDefaults to the new language passed in. In that case, the method should be:

- (void) setAppLanguage:(NSString *)newAppLanguage {
    _appLanguage = newAppLanguage; // implicit synchronize will set the ivar as _appLanguage
    [prefs setObject:newAppLanguage forKey:APP_LANGUAGE_KEY];
    [prefs synchronize];
}

Since the _appLanguage instance variable is set to strong by default, ARC will automatically add the necessary release and retain code, preventing a memory leak.

Also, if you are trying to create a private setter method, take - (void) setAppLanguage:(NSString *)appLanguage; out of the interface. If you're not trying to make a private setter, remove readonly from the property declaration.

J Shapiro
  • 3,861
  • 1
  • 19
  • 29