Property Declaration - ivar and getter values don't match - objective-c

I have a doubt regarding property redeclaration
Overview:
class "A" is the parent class with a readonly property int n1;
class "B" is the subclass, which redeclares the property as read write
using the setter of class "B" the property value is set as 20
when i print the value using the getter and the instance variable I seem to get different values
Points to note: - Memory management = ARC (Automatic Reference Counting)
Question:
When I print the values of self.n1 and _n1 why do I get different values ?
My expected behavior and actual behavior don't match why (Pls scroll down to see the actual vs expected) ?
Code: (in separate files)
A.h
#import<Foundation/Foundation.h>
#interface A : NSObject
#property (readonly) int n1;
- (void) display;
#end
A.m
#import "A.h"
#implementation A
#synthesize n1 = _n1;
- (void) display
{
printf("_n1 = %i\n", _n1); //I expected _n1 and self.n1 to display the same value
printf("self.n1 = %i\n\n", self.n1); //but they seem to display different values
}
#end
B.h
#import"A.h"
#interface B : A
#property (readwrite) int n1;
#end
B.m
#import"B.h"
#implementation B
#synthesize n1 = _n1;
#end
test.m
#import"B.h"
int main()
{
system("clear");
B* b1 = [[B alloc] init];
b1.n1 = 20;
[b1 display]; //Doubt - my expected behavior is different from actual behavior
return(0);
}
Expected Behavior:
_n1 = 20
self.n1 = 20
Actual Behavior:
_n1 = 0
self.n1 = 20

There are two ways of going about this. In neither case do you call #synthesize in the subclass. I'm surprised that compiles for you. I would expect an error like "Property 'n1' attempting to use ivar '_n1' declared in superclass 'A'". In any case it's definitely not something you can really do, which is why you're seeing strange behavior. (I remembered why you aren't seeing this error; it's because of the separate compile units. You're just winding up with different ivars.)
First, you need to understand #dyanmic. This is a way of telling the compiler "yes, I know you don't see an implementation for the required method here; I promise it'll be there at runtime." In the subclass, you will use #dynamic to let the compiler know that it's ok to inherit n1.
#implementation B
#dynamic n1;
#end
Now, you need to provide the setN1: method. IMO, subclasses shouldn't go messing with their superclass's ivars, so I approve of the fact that synthesized ivars are marked #private. In a second, I'll tell you how to undo that, but for now let's deal with my preferred solution:
Implement setN1: as a private method in A.
Expose it in B.
A.h
#interface A : NSObject
#property (readonly) int n1;
- (void) display;
#end
A.m
#import "A.h"
#interface A () // Private class extension, causes setN1: to be created but not exposed.
#property (readwrite) int n1;
#end
#implementation A
#synthesize n1 = _n1;
- (void) display {
...
}
#end
B.h
#import "A.h"
#interface B : A
#property (readwrite) int n1; // Tell the world about setN1:
#end
B.m
#import "B.h"
#implementation B
#dynamic n1; // Yes compiler, setN1: exists. I promise.
#end
Now, some people think it's fine for subclasses to mess with their superclass's ivars. Those people are wrong (ok, IMHO...) but it is possible in ObjC. You just need to declare the ivar #protected. This is the default when you declare ivars directly in the #interface (one of many reasons you shouldn't do this anymore). It would look like this:
A.h
#interface A : NSObject {
int _n1;
}
...
A.m -- remove the extra class extension that makes n1 writable in the superclass.
B.h -- no change
B.m
#implementation B
#dynamic n1;
- (void)setN1:(int)n1 {
_n1 = n1;
}
#end

I copied your code and verified the behavior that you are getting. I can explain the mechanics of it, but not the logic behind it.
Here is what's going on: each of the two #synthesize directives produces a hidden variable _n in its corresponding class. In addition, the directive synthesizes a getter for n1 in A, and a getter/setter pair in B. The getter of n1 in B overrides the getter of n1 in A; the setter does not, because there is nothing to override.
At this point, A's _n1 in B becomes orphaned: neither the getter of n1 nor its setter reference it. The setter references B's _n1, not A's. That's why you are seeing different values printed in the display method of A. Putting the method in B behaves the way that you would expect.
EDIT:
Naturally, the next question is how to make the behavior that you want. It turns out to be simple: do not synthesize the property in B, and implement a setter of _n1 in A's implementation file (without putting it in the interface, so that it remains read-only to the clients of your interface).
// This goes in A.m without a declaration in A.h
- (void) setN1:(int)n1 {
_n1 = n1;
}

Related

Can't rewrite Setter methods in subclasses

I am creating a new class in Obj-C called “Complex” which will deal with complex numbers.
I have 4 instance variables declared in the .h as follows:
#property (nonatomic) double re, im;
#property (nonatomic) double mod, arg;
and later, they are synthesized in the .m file:
#synthesize re, im; //real / imaginary parts
#synthesize mod, arg; //modulus / argument parts
In the complex class, I have many methods which involve functions/operations with complex numbers. Since each of these will only modify the complex number in either Cartesian/Polar form, I need a way to update the other form after a function.
I decided to do this by modifying the setter methods for all 4 variables (which is why I chose them to be nonatomic).
I’ve finished making this class, and everything works fine. However, I now would like to create 2 subclasses of Complex which would be CComplex (Cartesian) and PComplex (Polar). These subclasses would only work with the Cartesian/Polar instance variables.
It would be ideal to use these classes when you don’t need to interact with the other form as it increases speed when you are performing functions with Complex numbers several thousand/million times a second (Since the Updater in the setter methods would be skipped).
The problem I’m coming across is that I cannot rewrite the setter method in the subclasses, and nor can I recreate the instance variables (with the same names).
Can someone help me with this problem please? Thanks
Edit: Here's the relevant code:
Here's how I tried to implement the setter methods in my subclasses at first:
.h
#interface CComplex : Complex
#property (nonatomic) double re, im;
//
////Setter Methods
-(void) setRe:(double)r;
-(void) setIm:(double)i;
////
//
#end
#interface PComplex : Complex
#property (nonatomic) double mod, arg;
//
////Setter Methods
-(void) setMod:(double)m;
-(void) setArg:(double)a;
////
//
#end
.mm
#implementation CComplex
#synthesize re, im;
//
////Setter Methods
-(void) setRe:(double)r {
re = r;
}
-(void) setIm:(double)i {
im = i;
}
////
//
#end
#implementation PComplex
#synthesize mod, arg;
//
////Setter Methods
-(void) setMod:(double)m {
mod = m;
}
-(void) setArg:(double)a {
arg = a;
}
////
//
#end
I don’t know how you are overriding the setter but the common case should be:
#synthesize = re = _re;
- (void)setRe:(double)re {
// your code
_re = re;
}
Or instead of overriding the setter you can use lazy instantiation:
- (double)re {
if(!_re) {
_re = …// your code
}
return _re
}
To declare a public property, put in your class Ex: MyClass.h interface (not in the .m):
#import <Foundation/Foundation.h>
#interface MyClass : NSObject
#property (nonatomic) double re;
#end
To set a superclass property in a subclass you don't have to synthesize or redefine a property in a subclass:
super.re = ...;

What is the difference between the areas where you can declare instance variables in Objective-C? [duplicate]

Ever since starting to work on iOS apps and objective C I've been really puzzled by the different locations where one could be declaring and defining variables. On one hand we have the traditional C approach, on the other we have the new ObjectiveC directives that add OO on top of that. Could you folks helps me understand the best practice and situations where I'd want to use these locations for my variables and perhaps correct my present understanding?
Here's a sample class (.h and .m):
#import <Foundation/Foundation.h>
// 1) What do I declare here?
#interface SampleClass : NSObject
{
// 2) ivar declarations
// Pretty much never used?
}
// 3) class-specific method / property declarations
#end
and
#import "SampleClass.h"
// 4) what goes here?
#interface SampleClass()
// 5) private interface, can define private methods and properties here
#end
#implementation SampleClass
{
// 6) define ivars
}
// 7) define methods and synthesize properties from both public and private
// interfaces
#end
My understanding of 1 and 4 is that those are C-style file-based declarations and definitions that have no understanding whatsoever of the concept of class, and thus have to be used exactly how they would be used in C. I've seen them used for implementing static variable-based singletons before. Are there other convenient uses I'm missing?
My take from working with iOS is that ivars have been alost completely phased out outside of the #synthesize directive and thus can be mostly ignored. Is that the case?
Regarding 5: why would I ever want to declare methods in private interfaces? My private class methods seem to compile just fine without a declaration in the interface. Is it mostly for readability?
Thanks a bunch, folks!
I can understand your confusion. Especially since recent updates to Xcode and the new LLVM compiler changed the way ivars and properties can be declared.
Before "modern" Objective-C (in "old" Obj-C 2.0) you didn't have a lot of choices. Instance variables used to be declared in the header between the curly brackets { }:
// MyClass.h
#interface MyClass : NSObject {
int myVar;
}
#end
You were able to access these variables only in your implementation, but not from other classes. To do that, you had to declare accessor methods, that look something like this:
// MyClass.h
#interface MyClass : NSObject {
int myVar;
}
- (int)myVar;
- (void)setMyVar:(int)newVar;
#end
// MyClass.m
#implementation MyClass
- (int)myVar {
return myVar;
}
- (void)setMyVar:(int)newVar {
if (newVar != myVar) {
myVar = newVar;
}
}
#end
This way you were able to get and set this instance variable from other classes too, using the usual square bracket syntax to send messages (call methods):
// OtherClass.m
int v = [myClass myVar]; // assuming myClass is an object of type MyClass.
[myClass setMyVar:v+1];
Because manually declaring and implementing every accessor method was quite annoying, #property and #synthesize were introduced to automatically generate the accessor methods:
// MyClass.h
#interface MyClass : NSObject {
int myVar;
}
#property (nonatomic) int myVar;
#end
// MyClass.m
#implementation MyClass
#synthesize myVar;
#end
The result is much clearer and shorter code. The accessor methods will be implemented for you and you can still use the bracket syntax as before. But in addition, you can also use the dot syntax to access properties:
// OtherClass.m
int v = myClass.myVar; // assuming myClass is an object of type MyClass.
myClass.myVar = v+1;
Since Xcode 4.4 you don't have to declare an instance variable yourself anymore and you can skip #synthesize too. If you don't declare an ivar, the compiler will add it for you and it will also generate the accessor methods without you having to use #synthesize.
The default name for the automatically generated ivar is the name or your property starting with an underscore. You can change the generated ivar's name by using #synthesize myVar = iVarName;
// MyClass.h
#interface MyClass : NSObject
#property (nonatomic) int myVar;
#end
// MyClass.m
#implementation MyClass
#end
This will work exactly as the code above. For compatibility reasons you can still declare ivars in the header. But because the only reason why you would want to do that (and not declare a property) is to create a private variable, you can now do that in the implementation file as well and this is the preferred way.
An #interface block in the implementation file is actually an Extension and can be used to forward declare methods (not needed anymore) and to (re)declare properties. You could for instance declare a readonly property in your header.
#property (nonatomic, readonly) myReadOnlyVar;
and redeclare it in your implementation file as readwrite to be able to set it using the property syntax and not only via direct access to the ivar.
As for declaring variables completely outside of any #interface or #implementation block, yes those are plain C variables and work exactly the same.
First, read #DrummerB's answer. It a good overview of the whys and what you should generally do. With that in mind, to your specific questions:
#import <Foundation/Foundation.h>
// 1) What do I declare here?
No actual variable definitions go here (it's technically legal to do so if you know exactly what you're doing, but never do this). You may define several other kinds of things:
typdefs
enums
externs
Externs look like variable declarations, but they're just a promise to actually declare it somewhere else. In ObjC, they should only be used to declare constants, and generally only string constants. For instance:
extern NSString * const MYSomethingHappenedNotification;
You would then in your .m file declare the actual constant:
NSString * const MYSomethingHappenedNotification = #"MYSomethingHappenedNotification";
#interface SampleClass : NSObject
{
// 2) ivar declarations
// Pretty much never used?
}
As noted by DrummerB, this is legacy. Don't put anything here.
// 3) class-specific method / property declarations
#end
Yep.
#import "SampleClass.h"
// 4) what goes here?
External constants, as described above. Also file static variables can go here. These are the equivalent of class variables in other languages.
#interface SampleClass()
// 5) private interface, can define private methods and properties here
#end
Yep
#implementation SampleClass
{
// 6) define ivars
}
But very rarely. Almost always you should allow clang (Xcode) to create the variables for you. The exceptions are usually around non-ObjC ivars (like Core Foundation objects, and especially C++ objects if this is an ObjC++ class), or ivars that have weird storage semantics (like ivars that don't match with a property for some reason).
// 7) define methods and synthesize properties from both public and private
// interfaces
Generally you shouldn't #synthesize anymore. Clang (Xcode) will do it for you, and you should let it.
Over the last few years, things have gotten dramatically simpler. The side-effect is that there are now three different eras (Fragile ABI, Non-fragile ABI, Non-fragile ABI + auto-syntheisze). So when you see the older code, it can be a little confusing. Thus confusion arising from simplicity :D
I'm also pretty new, so hopefully I don't screw anything up.
1 & 4: C-style global variables: they have file wide scope. The difference between the two is that, since they're file wide, the first will be available to anyone importing the header while the second is not.
2: instance variables. Most instance variables are synthesized and retrieved/set through accessors using properties because it makes memory management nice and simple, as well as gives you easy-to-understand dot notation.
6: Implementation ivars are somewhat new. It's a good place to put private ivars, since you want to only expose what's needed in the public header, but subclasses don't inherit them AFAIK.
3 & 7: Public method and property declarations, then implementations.
5: Private interface. I always use private interfaces whenever I can to keep things clean and create a kind of black box effect. If they don't need to know about it, put it there. I also do it for readability, don't know if there are any other reasons.
This is an example of all kinds of variables declared in Objective-C. The variable name indicate its access.
File: Animal.h
#interface Animal : NSObject
{
NSObject *iProtected;
#package
NSObject *iPackage;
#private
NSObject *iPrivate;
#protected
NSObject *iProtected2; // default access. Only visible to subclasses.
#public
NSObject *iPublic;
}
#property (nonatomic,strong) NSObject *iPublic2;
#end
File: Animal.m
#import "Animal.h"
// Same behaviour for categories (x) than for class extensions ().
#interface Animal(){
#public
NSString *iNotVisible;
}
#property (nonatomic,strong) NSObject *iNotVisible2;
#end
#implementation Animal {
#public
NSString *iNotVisible3;
}
-(id) init {
self = [super init];
if (self){
iProtected = #"iProtected";
iPackage = #"iPackage";
iPrivate = #"iPrivate";
iProtected2 = #"iProtected2";
iPublic = #"iPublic";
_iPublic2 = #"iPublic2";
iNotVisible = #"iNotVisible";
_iNotVisible2 = #"iNotVisible2";
iNotVisible3 = #"iNotVisible3";
}
return self;
}
#end
Note that the iNotVisible variables are not visible from any other class. This is a visibility issue, so declaring them with #property or #public doesn't change it.
Inside a constructor it's good practice to access variables declared with #property using underscore instead self to avoid side effects.
Let's try to access the variables.
File: Cow.h
#import "Animal.h"
#interface Cow : Animal
#end
File: Cow.m
#import "Cow.h"
#include <objc/runtime.h>
#implementation Cow
-(id)init {
self=[super init];
if (self){
iProtected = #"iProtected";
iPackage = #"iPackage";
//iPrivate = #"iPrivate"; // compiler error: variable is private
iProtected2 = #"iProtected2";
iPublic = #"iPublic";
self.iPublic2 = #"iPublic2"; // using self because the backing ivar is private
//iNotVisible = #"iNotVisible"; // compiler error: undeclared identifier
//_iNotVisible2 = #"iNotVisible2"; // compiler error: undeclared identifier
//iNotVisible3 = #"iNotVisible3"; // compiler error: undeclared identifier
}
return self;
}
#end
We can still access the not visible variables using the runtime.
File: Cow.m (part 2)
#implementation Cow(blindAcess)
- (void) setIvar:(NSString*)name value:(id)value {
Ivar ivar = class_getInstanceVariable([self class], [name UTF8String]);
object_setIvar(self, ivar, value);
}
- (id) getIvar:(NSString*)name {
Ivar ivar = class_getInstanceVariable([self class], [name UTF8String]);
id thing = object_getIvar(self, ivar);
return thing;
}
-(void) blindAccess {
[self setIvar:#"iNotVisible" value:#"iMadeVisible"];
[self setIvar:#"_iNotVisible2" value:#"iMadeVisible2"];
[self setIvar:#"iNotVisible3" value:#"iMadeVisible3"];
NSLog(#"\n%# \n%# \n%#",
[self getIvar:#"iNotVisible"],
[self getIvar:#"_iNotVisible2"],
[self getIvar:#"iNotVisible3"]);
}
#end
Let's try to access the not visible variables.
File: main.m
#import "Cow.h"
#import <Foundation/Foundation.h>
int main(int argc, char *argv[]) {
#autoreleasepool {
Cow *cow = [Cow new];
[cow performSelector:#selector(blindAccess)];
}
}
This prints
iMadeVisible
iMadeVisible2
iMadeVisible3
Note that I was able to access the backing ivar _iNotVisible2 which is private to the subclass. In Objective-C all variables can be read or set, even those that are marked #private, no exceptions.
I didn't include associated objects or C variables as they are different birds. As for C variables, any variable defined outside #interface X{} or #implementation X{} is a C variable with file scope and static storage.
I didn't discuss memory management attributes, or readonly/readwrite, getter/setter attributes.

Modern Objective-C and #synthesize

I'm trying convert my code to Modern Objective-C style. How i read here http://www.techotopia.com/index.php/The_Basics_of_Modern_Objective-C": "In the case of Modern Objective-C, however, the synthesis takes place by default, making the use of #synthesize declarations unnecessary. When using default property synthesize, instance variable properties are accessible from within code using the property name prefixed with an underscore."
However, I have:
Relationship.h
#interface Relationship : NSObject <NSCoding>
//...
#property(nonatomic, weak) Person* first;
//...
#end`
OtherRelationship.h
#import "Relationship.h"
#interface OtherRelationship : Relationship
#end
OtherRelationship.m
#import "OtherRelationship.h"
#implementation OtherRelationship
#synthesize first = _first;
- (void)foo
{
NSLog(#"%#", _first);
}
and it's working. But when i delete
#synthesize first = _first;
i get "Use of undeclared identifier '_first'" error. Does inheritanced variables doesn't work with autosynthesize or should i looking for problem elsewhere?
The backing ivar in the superclass is #private to the subclass. That is, the subclass may call self.first, but not _first. If you want to #synthesize again, use a different name because you can't refer to _first. For example, replace with #synthesize first = _ffirst; or just drop the #synthesize.

Objective-C instance variables?

I'm sure my confusion here is just a result of being stuck in a "Java mindset" and not understanding how Obj-C differs in this case.
In Java, I can declare a variable in a class, like this, and each instance of that class will have it's own:
MyClass {
String myVar;
MyClass() {
// constructor
}
}
In Obj-C I tried to do the same thing by declaring a variable only in the .m file like this:
#import "MyClass.h"
#implementation MyClass
NSString *testVar;
#end
My expectation here was that this variable has a scope limited to this class. So I created a second class (identical):
#import "MySecondClass.h"
#implementation MySecondClass
NSString *testVar;
#end
What I'm seeing (and has me baffled) is that changing the variable in one class, affects the value seen in the other class. In fact, if I set a breakpoint, and then "Jump to Definition" of the variable, it takes me to th
I've created an extremely small Xcode project that demonstrates the problem here.
Change this:
#implementation MyClass
NSString *testVar;
#end
to:
#implementation MyClass {
NSString *testVar;
}
// methods go here
#end
and you'll get what you expected.
As you had it, you are actually creating a global variable. The two global variables were combined into one by the linker which is why both changed when you set one. The variable in curly braces will be a proper (and private) instance variable.
Edit: After being downvoted for no apparent reason, I thought I'd point out the "old" way of doing things, and the new way.
The old way:
SomeClass.h
#interface SomeClass : UIViewController <UITextFieldDelegate> {
UITextField *_textField;
BOOL _someBool;
}
#property (nonatomic, assign) BOOL someBool;
// a few method declarations
#end
SomeClass.m
#implementation SomeClass
#synthesize someBool = _someBool;
// the method implementations
#end
Now the new and improved way with the modern Objective-C compiler:
SomeClass.h
#interface SomeClass : UIViewController
#property (nonatomic, assign) BOOL someBool;
// a few method declarations
#end
SomeClass.m
#interface SomeClass () <UITextFieldDelegate>
#end
#implementation SomeClass {
UITextField *_textField;
}
// the method implementations
#end
The new way has several advantages. The primary advantage is that none of the implementation specific details about the class appear in the .h file. A client has no need to know what delegates the implementation needs. The client has no need to know what ivars I use. Now, if the implementation needs a new ivar or it needs to use a new protocol, the .h file doesn't change. This mean less code gets recompiled. It cleaner and much more efficient. It also makes for easier editing. When I'm editing the .m file and realize I need a new ivar, make the change in the same .m file I'm already editing. No need to swap back and forth.
Also note the implementation no longer needs an ivar or #synthesize for the property.
What you probably want (unless you're using a very old OS and compiler) is to just use property syntax. I.e.:
#interface MyClass : NSObject
// method declarations here ...
#property (copy) NSString* myVar;
// ... or here.
#end
This will do what you intended to do. This will implicitly synthesize an instance variable and a getter/setter pair for this variable. If you manually wanted to create the instance variable (you generally don't need that unless you need your code to work on very old MacOS versions), this is what the above code does under the hood to create the ivar:
#interface MyClass : NSObject
{
NSString* _myVar;
}
// method declarations here.
#end
Note the curly braces, which tell the compiler that this is not just a global variable somewhere in between the methods, but actually an instance variable that belongs to this object.
If you are creating the property only for internal use and don't want clients of your class to mess with it, you can hide this away a little bit in everything but the oldest ObjC compilers by using a class extension which "continues" the class declaration from the header, but can be placed separate from it (so usually in your implementation file). A class extension looks like a category without a name:
#interface MyClass ()
#property (copy) NSString* myVar;
#end
And you can either put your property declaration in there, or even ivar declarations (again wrapped in curly brackets). You can even declare the same property as readonly in the class interface, and then re-declare it identical, but as readwrite in the extension, so that clients only read it, but your code can change it.
Note that, if you didn't use ARC (that is, you've switched off the default of Automatic Reference Counting), you would have to set all your properties to nil in your dealloc method (unless they're set to weak or assign of course).
NB - All the above are #interface sections. Your actual code will go in separate #implementation sections. This is so you can have header files (.h) you can hand off to your class's clients that just contain the portions you intend them to use, and hide away implementation details in the implementation file (.m) where you can change them without having to worry someone might have accidentally used them and you'll break other code.
PS - Note that NSStrings and other objects that you want the immutable flavor of, but that also exist in a mutable flavor (i.e. NSMutableString) should always be copy properties, because that will turn an NSMutableString into an NSString so that nobody on the outside can change the mutable string underneath you. For all other object types, you generally use strong (or retain if not ARC). For your class's owner (e.g. its delegate) you usually use weak (or assign if not ARC).
In Java
MyClass {
String myVar;
MyClass() {
// constructor
}
}
In Objective-c
MyClass.h
#interface MyClass : NSObject{
NSString* str; // Declaration
}
#end
MyClass.m
#implementation MyClass
-(void)initializieTheString
{
//Defination
}
#end
In objective-c, you define the variable as private by doing like so
MyClass.h
#interface MyClass : NSObject{
NSString* _myTestVar; // Declaration
}
#end
and refer to it in the implementation class by doing like so
MyClass.m
#import "MyClass.h";
#implementation MyClass
-(void)initializieTheString
{
_myTestVar= #"foo"; //Initialization
}
#end

#property and #synthesize

I'm very new to Objective C. (Two days now). When read about #synthesize, it seemed to overlap with my understanding #property (which I thought I understood) ... So, some details need to be ironed out in my mind ... it's bugging me.
Please correct me if I'm wrong about differences of #property and #synthesize:
If you declare a #property in your #interface, then you're telling the world that users can expect to use standard getters and setters for that property. Futhermore, XCode will make generic getters and setters for you. ... BUT, To what degree does that happen with the #property declaration? ( I.E. does that mean "completely" ... like unseen declarations for it in your #interface, and also unseen code in your #interface?
-Or-
Does #property take care of the unseen code declarations in your #interface only - whereas #synthesize takes care of the unseen code implementation in your #implementation section? )
First, note that the latest version of Xcode does not require #synthesize at all anymore. You can (and should) just omit it. That said, here's what the pieces do.
#property is a declaration of accessors. It is just a declaration. There is very little difference between the following:
#property (nonatomic, readwrite, strong) NSString *something;
vs.
- (NSString *)something;
- (void)setSomething:(NSString)aSomething;
The main difference is that declaring these methods using #property lets the compiler automatically generate (synthesize) the implementations for you. There is no requirement that you let the compiler do it for you. You are absolutely free to implement something and setSomething: by hand, and it is common to do. But, if you don't implement them by hand, the compiler will automatically create an ivar for you called _something and create a reasonable implementation for the getter and setter.
In older versions of Xcode, you had to explicitly request the auto-generation using the #synthesize keyword. But that is no longer required. Today, the only reason to use #synthesize is if you want the ivar to have a non-standard name (never do that).
A key point here is that the methods something and setSomething: are just methods. There is nothing magical about them. They're not special "property methods." They're just methods that by convention access a piece of state. That piece of state is often stored in an ivar, but does not need to be.
To be even more clear: object.something does not mean "return the ivar named _something from object." It means "return the result of [object something], whatever that does." It is common for that to return the value of an ivar.
You should declare all of your state (internal and external) using #property declarations, and you should avoid directly declaring ivars. You should also always access your properties via their accessors (self.something), except in the init and dealloc methods. In init and dealloc, you should directly use the ivar (_something).
#property declares a property on your class with whatever atomicity and setter semantics you provide.
With Xcode 4.4, autosynthesis is available wherein you are provided with a backing ivar from your property without declaring it in #synthesize. This ivar has the form of _propertyName where your property name is propertyName.
Objective-C #property and #synthesize
#property
generates get/set method
today(from Xcode v4.4 with the LLVM v4.0) #property additionally uses #synthesize inside
#synthesize propertyName = _propertyName
#synthesize:
generates a new iVar or link with existing iVar
generates an implementation of the get/set method with an appropriate iVar
[Case when #synthesize can be used]
#property
#interface SomeClass : NSObject
#property NSString *foo;
#end
//generated code
#interface SomeClass : NSObject
- (NSString *)foo;
- (void)setFoo:(NSString)newFoo;
#end
#synthesize pattern
#synthesize <property_name> = <variable_name>;
//Using
//1. Specify a variable. New variable(variableName) will be generated/linked with existing
#synthesize propertyName = variableName
//if variableName is not exist it generates:
//NSString *variableName;
//read access
NSString *temp = variableName;
//2. Default. New variable(propertyName - the same name as a property) will be generated/linked with existing
#synthesize propertyName
//is the same as
//#synthesize propertyName = propertyName
//if propertyName is not exist it generates:
//NSString *propertyName;
//read access
NSString *temp = propertyName;
//if you specify not-existing <property_name> you get
//Property implementation must have its declaration in interface '<class_name>' or one of its extensions
previously you had to use next syntax:
#interface SomeClass : NSObject
{
//1. declare variable
NSString *_foo;
}
//2. create property
#property NSString *foo;
#end
#implementation SomeClass
//3. link property and iVar
#synthesize foo = _foo;
#end
But today you can use next syntax
#interface SomeClass : NSObject
//1. create property
#property NSString *foo;
#end
Next, the same code, will be generated for both cases
#interface SomeClass : NSObject
{
//variable
NSString *_foo;
}
//getter/setter
- (void)setFoo:(NSString *)newFoo;
- (NSString *)foo;
#end
#implementation SomeClass
- (void)setFoo:(NSString *)newFoo
{
_foo = newFoo;
}
- (NSString *)foo
{
return _foo;
}
#end