I'm fairly new to objective-c, and I want to write a model class in iOS 7 using ARC, but I'm not sure whether I need the synthesize in the .m file. Could any one give me some advice on this?
//user.h
#interface User : NSObject
#property(nonatomic, assign) NSInteger age;
#property(nonatomic, copy) NSString *firstname;
#property(nonatomic, copy) NSString *lastname;
#end
//user.m
#implementation User
#synthesize age, firstname, lastname;
#end
Now comes my question:
Is the user.m file's synthesize necessary or not if in another class (e.g. ViewContoller class), I want to read & set the User class's age property, or firstname/lastname properties?
Not needed . Modern objective C compiler will auto synthesize the properties for you. Its a compiler feature started with the LLVM 4.0 comes with Xcode 4.4. If you just want the default behaviour of property no need of manual #synthesize.
Related
If I have a property like this:
//test.h
#interface test
#property (nonatomic, readonly, weak) NSObject x;
#end
redefined in the implementation file to be read/write:
// test.m
#interface test ()
#property (nonatomic, readwrite) NSObject x;
#end
I used weak in .h, but I said nothing in the extension, will the property keep the 'weak' specifier, or will it change to 'strong'?
Will the keywords strong/assign/weak be overwritten when the property is redefined?
A simple test with Xcode 5.1.1 shows the weak attribute is kept. The same is true for the assign and strong attributes - you can specify them in the .h and omit them in the .m, if you do include them in the .m the two must match.
Having said that, I do not know if this is documented anywhere. But then the semantics of Objective-C are not formally defined anywhere either. So use at your own risk.
Recommendation: just repeat it.
Since upgrading to Xcode 5.1, I'm starting to see the following warning in some code my project uses. I'm trying to figure out what it means.
Warning: Auto property synthesis will not synthesize property 'responseHeader' because it is 'readwrite' but it will be synthesized 'readonly' via another property
The code where it's occurring, in the .m file:
#interface S3Response ()
#property (nonatomic, readwrite, retain) NSDictionary *responseHeader;
#end
The previous declaration of the property, in the .h file:
#property (nonatomic, readonly) NSDictionary *responseHeader;
There is no #synthesize statement for that property, nor are responseHeader or setResponseHeader defined as methods. There is however an explicit definition of an ivar named responseHeader.
Seems pretty straightforward to me: property is declared as read-only for users of the class, but read-write locally so the class can set it.
What does this warning mean, and what should I do about it?
That code seems to be from the AWS SDK for iOS,
and S3Response is a subclass of AmazonServiceResponse.
The public AmazonServiceResponse interface defines a read-only property
#interface AmazonServiceResponse:NSObject
// ...
#property (nonatomic, readonly) NSDictionary *responseHeader;
#end
which is redefined as read-write in a class extension in the implementation file:
#interface AmazonServiceResponse ()
#property (nonatomic, readwrite, retain) NSDictionary *responseHeader;
#end
Now the subclass S3Response also wants read-write access to this property,
and therefore also defines in the class extension of its implementation file:
#interface S3Response ()
#property (nonatomic, readwrite, retain) NSDictionary *responseHeader;
#end
The compiler complains because – when compiling "S3Response.m" – it does not know
that a setter for the property exists in the superclass (it does not read
the implementation file of the superclass at that point). Also the compiler cannot
simply synthesize a setter in the subclass, because it cannot not know that the
property is backed-up by an instance variable in the superclass.
But you know that a setter will be generated, so you can remove the warning by
adding a #dynamic declaration to the subclass implementation:
#implementation S3Response
#dynamic responseHeader;
...
#dynamic is a "promise" to the compiler that all necessary accessor methods will
be available at runtime.
The problem here is as follows.
By default, if don't write ownership (weak/retain/strong/assign) explicitly, xCode will check the type automatically. So in case of NSDictionary it will be strong. Thus, in interface you will have
#property (nonatomic, readonly, strong) NSDictionary *responseHeader;
Then it will be contradict you private implementation definition
#property (nonatomic, readwrite, retain) NSDictionary *responseHeader;
Compilator doesn't match strong and retain under property synthesizing though it is formally the same thing.
To cure situation you can write retain in both cases, or more correct, you should not write retain at all. It will be strong by default in both definitions.
Here are 2 methods to assign property in Objective-C :
METHOD 1
// in header
#interface Book : NSObject {
NSString *_title;
}
#property (nonatomic, retain) NSString *title;
// in implementation
#implementation Book
#synthesize title = _title;
METHOD 2
// in header
#interface Book : NSObject {
NSString *title;
}
#property (nonatomic, retain) NSString *title;
// in implementation
#implementation Book
#synthesize title;
What are the difference? I use Method 1 recently, as more tutorials recommend Method 1, but nobody explains why.
The difference is the names. In #2 the property and instance field have the same name. In #1 they have different names.
The advantage to #1 is that it's difficult to accidentally reference the property when you mean the instance field or vice-versa. Referencing the wrong one can lead to having a object retained twice or not retained at all.
The advantage to #2 is that it's marginally simpler, and it works fine if you're careful and a bit formal in your use of things.
[And, I see, one flavor specifies assign and the other retain, which is a whole different lecture. You'd not normally use assign with an object pointer.]
Firstly, I recommend you use copy instead of retain(and assign) for NSString type of instance. If it's Mutable, then it gets copied; If not, then it just gets retained.
Maybe you'll like THIS DISCUSSION.
And for you question, the difference is that first one use the same name and the second one use the different name for iVar & property.
Actually, you have a METHOD 3 to use:
// in header
#interface Book : NSObject {
}
#property (nonatomic, copy) NSString *title;
// in implementation
#implementation Book
#synthesize title;
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. For example, given the following class declaration and implementation.
Here is a sample code of official doc, you can make it clear( it includes difference between your METHOD 1 & METHOD 2):
#interface MyClass : NSObject {
float sameName;
float otherName;
}
#property float sameName;
#property float differentName;
#property float noDeclaredIvar;
#end
#implementation MyClass
#synthesize sameName;
#synthesize differentName=otherName;
#synthesize noDeclaredIvar;
#end
The compiler for the legacy runtime would generate an error at #synthesize noDeclaredIvar; whereas the compiler for the modern runtime would add an instance variable to represent noDeclaredIvar.
Note: iPhone applications and 64-bit programs on Mac OS X v10.5 and later use the modern version of the runtime. Other programs (32-bit programs on Mac OS X desktop) use the legacy version of the runtime. You can refer it HERE).
However, I suggest to use METHOD 1 or METHOD 3. As you can just use self.title in code, the property will help you manage the alloc & release. If you use METHOD 2, you may mix title with self.title(but _title is more clear, uh?). :)
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Properties and Instance Variables in Objective-C 2.0
I'm confused by these two code segments:
First:
//.h
#interface Student : NSObject {
}
#property (nonautomic, copy) NSString *name;
#property (nonautomic, retain) NSNumber *age;
#end
//.m
#implementation Student
#synthesize name;
#synthesize age;
#end
Second:
//.h
#interface Student : NSObject {
NSString *name; // <<============ difference
NSNumber *age; // <<============ difference
}
#property (nonautomic, copy) NSString *name;
#property (nonautomic, retain) NSNumber *age;
#end
//.m
#implementation Student
#synthesize name;
#synthesize age;
#end
Both of these can work. So is it necessary to declare variables in the {}?
Starting with the modern runtime (x86_64 and ARM6...and iOS Simulator) you no longer need to declare synthesized ivars. In the first example #synthesize is adding the instance variable for you.
Agree with #Joshua. I too was confused with this in the beginning. It's basically old convention vs new convention after the runtime updates. I think Apple realized that declaring ivars was redundant when you're gonna declare #property, so why not let the #synthesize take care of it when it creates the setters and getters. One less statement for us to write, yay!
(Some of these convention changes were explained in one of the earlier WWDC videos... i think)
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.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Properties and Instance Variables in Objective-C 2.0
Objective-C Properties with or without instance variables
What is the difference between the following two pieces of code? Both are compilable and I don't know which is "correct".
#interface JTPlayer : NSObject {
NSString *userId;
NSString *name;
BOOL inBattle;
}
#property (nonatomic, copy) NSString *userId;
#property (nonatomic, copy) NSString *name;
#property (nonatomic, assign) BOOL inBattle;
#end
and
#interface JTPlayer : NSObject
#property (nonatomic, copy) NSString *userId;
#property (nonatomic, copy) NSString *name;
#property (nonatomic, assign) BOOL inBattle;
#end
One is the previous version of declaring properties. As you can see, you needed to declare variables by hand, and then declare properties applied to those variables.
The second is the newer version that manages the rest for you, declaration of variables and correspondences with properties.
Both blocks are correct, but the first one requires more keystrokes. This code (both versions) is supposed to belong to a header file, accompanied with a source file with .m extension that contains the implementation. This implementation will contain #synthesize instructions, that generate the getter and setter methods for you.
For more information, you really should read the Apple Guide to Objective-C. Also check out http://www.raywenderlich.com .
The current version of the Objective-C runtime does not require you to specify you instance variables for properties. #synthesize will add them for you automatically.
Check out this article that I put up awhile ago. It explains about instance variables and properties.
Objective-C Properties with or without instance variables