开发者

Don't need to put properties inside the interface?

I think I got a bad book on Objective-C. It said to put variables I'm going to use and make available to other classes inside the interface brackets, and then declare a property of the same thing.

@interface appDel开发者_运维百科egate : NSObject <UIApplicationDelegate>  {
    NSNumber *myNumberOtherClassesCanUse;
}
@property (nonatomic, retain) NSNumber *myNumberOtherClassesCanUse;

However, I saw another question answered that made me think I didn't have to put them inside the brackets, so I tried that and it still works fine.

I bought another book and it doesn't explain it either, so can someone tell me or point me to documentation on when I have to put them inside the brackets AND make them properties?


A long and complicated answer:

The class fields, the things inside the interface brackets:

@interface MyClass : SomeSuperclass
{
  int someNumber_; /* this stuff */
}

add actual bytes to your object. An objective-C class is really, underneath all the fluff, just a large C struct; and these are the fields of that struct. (You can even get at them with -> style C pointer syntax, although the compiler will yell at you if you do so without an @public in there; the correct way to access these fields is by bare name like any other variable.)

A property declaration like:

@property (nonatomic, assign, readwrite) int someNumber;

is obj-C 2.0 shorthand for a pair of method declarations like:

-(int)someNumber;
-(void)setSomeNumber:(int)newNumber;

which adds nothing to your class; it just declares to the world that here are some operations that can be performed on this class. By convention, methods like this are supposed to get and set a field value, or at least behave like they do. Having methods like this lets you use the obj.prop and obj.prop = val dot-syntax to call them.

A synthesize directive:

@synthesize someNumber;

optionally creates these methods for you at runtime, using standard builtin behaviors (informed by that "nonatomic, assign" stuff), AND optionally creates a field of the same name to get and set. A directive like @synthesize someNumber = someNumber_; names the created field "someNumber_" instead. If you declared such a field in the @interface block, like I did above, it uses that field; otherwise it quietly inserts an appropriate field of its own. This quiet field insertion is new behavior since the 4.x simulator; before that you had to declare all your fields in the @interface{} block, period.

In summary: @interface{...} describes the physical fields of your object; @property()... describes ways your object is supposed to be used; and @synthesize is shorthand for implementing basic getter/setters and inserting extra fields if needed. I usually let @synthesize do its thing, and leave my @interface{} block empty until I have an actual need to declare a field explicitly, usually to look at it with the debugger.

[as of the latest SDKs, some of the above is dated. In particular, @synthesize is now optional, and instance vars can be declared in the @implementation in the .m file.]


You don't generally have to put them in the @interface brackets when you are using @property and @synthesize as the synthesize will create the variable for you if it does not detect a backing ivar declared in the class.

The brilliant iOS recipes book states that the iOS device runtime has always had this capability but it was only added to the simulator in iOS 4. So considering the simulator is used a lot in development it is probably just a habit that stuck for some.

And to back that up at the very bottom of this Apple doc for The Objective-C Programming Language

There is one key difference: the modern runtime supports instance variable synthesis whereas the legacy runtime does not.


Trust your compiler, not your books.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜