开发者

Question about ivars and @property's on the iPhone

I have a question about how instance variables work and when to use the @property. Here is an example interface file I am working with

@interface PackageModel : NSObject {
    NSString *tracking;
    NSString *carrier;
    NSString *status;
    NSMutableDictionary *events;

    // Connection ivars
    NSMutableData *receivedData;

    // Parsing ivars
    int tagLevel;
    NSMutableArray *tagTree;
    NSString *parentTag;
    NSString *currentTag;
}

@property (nonatomic, retain) NSMutableData *receivedData;

- (id)initWithTrackingString:(NSString *)string;
- (void)getPackageDataWithEvents;
- (void)printMe;

@end

How can I access these in the file's code. Can I access trackin开发者_如何学Gog, carrier, and status in this class's methods just by using something like

tracking = [[NSString alloc] initWithString:@"Hello World"];

Also, what variables need to be put in the dealloc? Only the variables I have in the @property/@synthesize? Or do I need to release all the instance variables in the dealloc method.

I am just looking for some clarification on how instance variables work in Objective-C. Thanks.


@property declarations are nothing more than compiler-generated getter and setter methods. That's it. Just the methods. Obviously, you have to be getting and setting something, so we create the ivar that goes along with the getters and setters. In your example above, your compiler is generating:

- (NSMutableData *) receivedData;
- (void) setReceivedData:(NSMutableData *)newReceivedData;

The getter returns the value in the receivedData instance variable, and the setter changes the value in the receivedData instance variable.

(Side note: with the 64-bit runtime, you can skip declaring the instance variable, but I still like to put it in just to be explicit)

As for what you should do in your dealloc method, you need to release the instance variables that have been retained or copyed. So in your example, you'll need to do [receivedData release]; in your dealloc method, because when you set the receivedData ivar, you retained the new value (that's what the retain means on the @property line). If you don't specify either retain or copy in the @property declaration, then it defaults to assign, and you don't have to do anything. Beyond this, you'll need to release any other instance variables that you retained yourself (ie, not through an @property (retain) setter).

For your last question, yes you can just do:

tracking = [[NSString alloc] initWithFormat:@"Hello, %@!", @"world"];

Inside your own class, you have direct access to all your own instance variables (and any protected and public ivars of your super classes).


Something not covered is that your last line of code could be:

tracking = @"Hello World";

The "@" is basically creating the string object for you.


Yikes, that's a really broad question. I highly recommend you read Apple's Objective-C Primer and their full reference to the language.

As a starter, you ask: "How can I access these in the file's code?" You don't specify which file. Inside the @implementation of PackageModel, you can simply refer to the instance variables like you do in your tracking example. You cannot easily access them from other classes.

If, however, you make them @properties and @synthesize them, you can access them within the class itself like self.tracking. Moreover, you can now also access them from other classes, as well.

PackageModel *model = [[PackageModel alloc] init];
model.receivedData = [NSMutableData data];

Another advantage to the properties is that they can handle memory management for you. When done correctly, you really don't need to worry about retains and releases very much. That receivedData property on your PackageModel class will automatically release any previously retained objects before assigning the new data. It's glorious. This happens because the compiler automatically 'synthesizes' the setters and getters, and then calls them for accesses through the dot operator.

One final note is that these setters and getters are automatically protected by a @synchronize block that ensures that the operations happen atomically (and that a second thread couldn't disrupt the activity midway through). This is largely unneeded on an iPhone and causes a decent amount of overhead, so it behooves you to declare all your properties as nonatomic in addition to your read/write permissions and memory management scheme.


One advantage to using @property/@syntehsize is that it pushes you to use accessor methods for the ivars. This helps you to be better about memory management. On the iPhone, have you to be aware of retain counts for two big reasons: 1. Keep memory usage down. 2. Avoid crashes. When you access ivars directly, you run the risk of forgetting to retain a variable and then go to access it later on only to find out that it has been freed. Or the opposite, you forgot to release a variable, and pretty soon you've built up so much memory that the iPhone OS tells your application to terminate.

Using accessor methods, even inside the class, are generally a good idea. The only place I normally set ivars directly are inside the init method of the class. I also generally release all my ivars inside the dealloc method.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜