Do declared properties require a corresponding ins

2019-01-01 07:23发布

问题:

Do properties in Objective-C 2.0 require a corresponding instance variable to be declared? For example, I\'m used to doing something like this:

MyObject.h

@interface MyObject : NSObject {
NSString *name;
}
@property (nonatomic, retain) NSString *name;
@end

MyObject.m

@implementation
@synthesize name;
@end

However, what if I did this instead:

MyObject.h

@interface MyObject : NSObject {
}
@property (nonatomic, retain) NSString *name;
@end

Is this still valid? And is it in any way different to my previous example?

回答1:

If you are using the Modern Objective-C Runtime (that\'s either iOS 3.x or greater, or 64-bit Snow Leopard or greater) then you do not need to define ivars for your properties in cases like this.

When you @synthesize the property, the ivar will in effect be synthesized also for you. This gets around the \"fragile-ivar\" scenario. You can read more about it on Cocoa with Love



回答2:

In your interface, you can formally declare an instance variable between the braces, or via @property outside the braces, or both. Either way, they become attributes of the class. The difference is that if you declare @property, then you can implement using @synthesize, which auto-codes your getter/setter for you. The auto-coder setter initializes integers and floats to zero, for example. IF you declare an instance variable, and DO NOT specify a corresponding @property, then you cannot use @synthesize and must write your own getter/setter.

You can always override the auto-coded getter/setter by specifying your own. This is commonly done with the managedObjectContext property which is lazily loaded. Thus, you declare your managedObjectContext as a property, but then also write a -(NSManagedObjectContext *)managedObjectContext method. Recall that a method, which has the same name as an instance variable/property is the \"getter\" method.

The @property declaration method also allows you other options, such as retain and readonly, which the instance variable declaration method does not. Basically, ivar is the old way, and @property extends it and makes it fancier/easier. You can refer to either using the self. prefix, or not, it doesn\'t matter as long as the name is unique to that class. Otherwise, if your superclass has the same name of a property as you, then you have to say either like self.name or super.name in order to specify which name you are talking about.

Thus, you will see fewer and fewer people declare ivars between the braces, and instead shift toward just specifying @property, and then doing @synthesize. You cannot do @synthesize in your implementation without a corresponding @property. The Synthesizer only knows what type of attribute it is from the @property specification. The synthesize statement also allows you to rename properties, so that you can refer to a property by one name (shorthand) inside your code, but outside in the .h file use the full name. However, with the really cool autocomplete that XCode now has, this is less of an advantage, but is still there.

Hope this helps clear up all the confusion and misinformation that is floating around out there.



回答3:

it works both ways but if you don\'t declare them in the curly braces, you won\'t see their values in the debugger in xcode.



回答4:

From the documentation:

In general the behavior of properties is identical on both modern and legacy runtimes (see “Runtime Versions and Platforms” in Objective-C Runtime Programming Guide). There is one key difference: the modern runtime supports instance variable synthesis whereas the legacy runtime does not.

For @synthesize to work in the legacy runtime, you must either provide an instance variable with the same name and compatible type of the property or specify another existing instance variable in the @synthesize statement. With the modern runtime, if you do not provide an instance variable, the compiler adds one for you.



回答5:

If you are using XCode 4.4 or later it will generate instance variable synthesizing code for you.

You just have to declare properties like below; it will generate synthesizing code and instance variable declaring code for you.

@property (nonatomic, strong) NSString *name;

it will generate synthesizing code as

@synthesize name = _name;

and you can access instance variable using _name it is similar to declare

NSString* _name

but if you declare read-only property it like

@property (nonatomic, strong, readonly) NSString *name;

it will generate code

@synthesize name;

or

@synthesize name = name; 

So you should access instant variable name with out prefix \"_\" any way you can write your own synthesizing code then compiler will generate code for you. you can write

@synthesize name = _name;


回答6:

The Objective-C Programming Language: Property Implementation Directives

There are differences in the behavior of accessor synthesis that depend on the runtime (see also “Runtime Difference”):

  • For the legacy runtimes, instance variables must already be declared in the @interface block of the current class. If an instance variable of the same name as the property exists, and if its type is compatible with the property’s type, it is used—otherwise, you get a compiler error.

  • For the modern runtimes (see “Runtime Versions and Platforms” in Objective-C Runtime Programming Guide), instance variables are synthesized as needed. If an instance variable of the same name already exists, it is used.