Vikings
Vikings

Reputation: 2527

iPhone Instance Variable Issue

I am trying to figure out what is the purpose of synthesizing myString to the instance variable _myString.

What is the purpose of doing this? I tend to notice a lot of people doing this.

Also I should release the instance variable and set the instance variable to nil, is that correct.

ViewController.h

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController
{
    NSString *_myString;
}

@property (nonatomic, retain) NSString *myString;

@end

ViewController.m

#import "ViewController.h"

@implementation ViewController

@synthesize myString = _myString;

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.myString = [[NSString alloc] initWithFormat:@"Hello"];

    _myString = [[NSString alloc] initWithFormat:@"Goodbye"];

    NSLog(@"%@\t%@", self.myString, _myString);
}

- (void)viewDidUnload
{
    _myString = nil;
    [super viewDidUnload];
}

- (void)dealloc
{
    [_myString release];
    [super dealloc];
}

@end

Upvotes: 2

Views: 230

Answers (4)

MrTJ
MrTJ

Reputation: 13192

When you @synthesize an object type property in objective c, the compiler will generate two hidden methods for that instance variable. Thus when you refer myObject.myString, not only the pointer of _myString will be returned, but the generated - (NSString*) myString method will be called. Similarly if you assign something to the property: myObject.myString = @"foo"; it will be compiled to [myObject setMyString:@"foo"];.

What is in - (NSString*) myString and - (void) setMyString:(NSString*) theString depends on the keywords you specify when declaring the property. The most common is assign that simple assigns the pointer you give:

- (void) setMyString:(NSString*) theString 
{
     _myString = theString;
}

- (NSString*) myString
{
    return _myString;
}

This makes not too much difference from declaring _myString a public variable, but it is more explicit way to say that this variable can be directly accessed from outside.

In turn, retain generates similar setter method (getter method will be the same):

- (void) setMyString:(NSString*) theString 
{
     [theString retain];
     [_myString release];
     _myString = theString;
}

You can see that this takes care of the memory management of the object you passed into the property. In other words you can be sure that the object will be not released until you have it in your property, thus you don't have to retain it manually when you take its ownership. This makes much more convenient to write code that manages the memory without leaks. Note, in the dealloc you still have to apply nil to your property in order to release the last object it stored.

Another category of properties when their data does not come from instance variables but from some other data source like a database. The auto-generated properties of the Managed Objects of Core Data for example work so.

At last, you can also define your own getters and setters. A good idea for example to write a property wrapper around some frequently used NSUserDefaults settings, that will facilitate its access:

@interface Bar 

@property (nonatomic, assign) NSString* foo;

@end

@implementation Bar

- (void) setFoo:(NSString *)theFoo
{
    [[NSUserDefaults standardUserDefaults] setObject:theFoo 
                                              forKey:@"settings.foo"];
}

- (NSString*) foo
{
    return [[NSUserDefaults standardUserDefaults] 
        stringForKey:@"settings.foo"];
}

@end

myBar.foo = @"foobar"; // automatically persisted between application runs

Read these also: Advanced memory management and Declared properties in objective C

Upvotes: 3

arindam
arindam

Reputation: 536

It is declared to differentiate between private variables and public variables within an object. It is a completely optional.

See this: When is UIViewController viewDidUnload called? and What exactly must I do in viewDidUnload?.

It might help you.

Upvotes: 0

lawicko
lawicko

Reputation: 7344

People tend to synthesize properties to underscore prefixed variables not to mistake the two when writing other code. For example:

// ... do sth
myString = @"Foo";
// ... do sth else ...
self.myString = @"Bar";

First instruction accesses the variable directly, second one uses the synthesized setter. When you synthesize without pointing to the specific variable, then the variable with the same name as the property is created for you:

@synghesize myString; // this creates myString variable for you

Instead of doing this, people create the underscore prefixed variables to avoid accessing it directly by mistake. When they do it, the first instruction myString = @"Foo" doesn't compile anymore, which makes it very easy to prevent nasty bugs like the ones when you bypass the getter or setter by mistake.

As for your second question, use ARC if possible. If not, you should first release the variable, then reset the pointer. In the code that you presented viewDidUnload will be called earlier than dealloc, so you will have a memory leak becasue _myString will point to nil before release is called on it.

Upvotes: 0

lnafziger
lnafziger

Reputation: 25740

self.myString (technically [self myString]) is actually accessing and setting the ivar _myString through the function in this object written like this:

-(NSString *)myString {
    // code that is automatically generated by the @synthesize statement OR
    // code that you write which over-rides the generated accessor.
    // both of which generally return the value stored in _myString
}

-(void)setMyString:(NSString *)newString{
    // code that generally changes the value of _myString
}

Using _myString directly bypasses these functions and accesses the ivar directly.

Upvotes: 1

Related Questions