#synthesize'd Objective-C properties are great. Sometimes though, it's needed to customize the behavior of a getter or setter. I'm searching for a list of default implementations for all the 12 (3*2*2) different scenarios:
assign/retain/copy
nonatomic or not
getter and setter
EDIT I'm searching for standard Objective-C implementations, not the low-level Clang implementation of synthesized properties. Unfortunately, Apple's documentation only mentions a few of above's scenarios but not the more "exotic" atomic ones.
It's available in the source code of Clang. See this, in particular CodeGenFunction::GenerateObjCGetter and CodeGenFunction::GenerateObjCSetter. Note that it's not that Objective-C code is first generated and then compiled; it's directly done. The rough idea is that for nonatomic assigned mode, or in the GC-only mode, the direct reading/writing code is generated. Everything else is handled by secret runtime functions objc_setProperty and objc_getProperty.
Their definitions, in turn, can be found here.
In any case, it's not something you want to copy first and then modify. Apple might change the detailed form of the implementation any time, without breaking the semantics.
I would recommend you to just write the standard setter/getter we used to write before properties are introduced.
Note that you can have #synthesize foo and your custom setter setFoo: in your .m file. Then only the getter is generated. Similarly with the other case.
Or, one way is to synthesize a property with a slightly different name from the one you want to customize. Suppose you have
#property (nonatomic,retain) NSString*foo;
in your .h file. I would put in the .m file
#interface Foo (private)
#property (nonatomic,retain) NSString*_foo;
#end
#implementation Foo
#synthesize _foo;
and put the customization in foo: and setFoo::
-(NSString*)foo{
... do something ...
return self._foo;
}
Related
What is the default property value if I just do the following:
#property (nonatomic) UIButton *myButton;
in a non-ARC project. Is this retain or assign?
Since in non-ARC projects of any size its pretty important to see exactly whats retained and assigned or copied, I would really recommend not using that default.
Its hard to read when your looking at a class with several properties that may have many other attributes such as readonly, atomic and non atomic. getter= etc
Although its not perfect putting a #define in a constant header like
#define ASSIGN nonatomic, assign
#define RETAIN nonatomic, retain
for your most common usages can make your property definitions a little more explicit
so that when you eventually catch up to writing your dealloc methods its a really quick check to see what you need to release.
Most of my property definitions looks like
#property (ASSIGN) Foo* foo;
or
#property (RETAIN) Foo* foo;
Thats what I do and it keeps the noise on property definitions down and makes the code read a little easier when troubleshooting or perfecting manual memory managed apps.
If I define a property in Objective-C 2.0 as follows:
#property (readwrite, assign) NSObject *theObject;
I have to create getter & setter methods somehow. As far as I can tell, I have three options for this.
Manually code the implementations of - (NSObject *)theObject & - (void)setTheObject:(NSObject *)object
Use #synthesize to automatically generate both methods, or
Use #dynamic to automatically generate any of the two methods that I don't choose to override.
Am I understanding this correctly? Also, how does the use of different #property arguments affect the results of #synthesize & #dynamic? (For example, nonatomic & weak)
You have misunderstood the difference between #synthesize and #dynamic.
#synthesize will generate the getter and setter methods of the properties if the getter and/or setter has not already been implemented manually. This is what you currently believe #dynamic does.
#dynamic is used when you don't want the runtime to automatically generate a getter and setter AND you haven't implemented them manually. Basically, #dynamic is telling the compiler that the getter/setter will be provided dynamically at runtime using some sort of runtime magic.
For example, the Objective-C Runtime Programming Guide says:
You can implement the methods `resolveInstanceMethod:` and `resolveClassMethod:`
to dynamically provide an implementation for a given selector for an instance
and class method respectively.
I suggest you read the Declared Properties section of The Objective-C Programming Language as this explains in much more detail the way #property, #synthesize and #dynamic work along with all the attributes like nonatomic and weak.
#dynamic tells the compiler that the accessor methods are provided at runtime.
With a little bit of investigation I found out that providing accessor methods override the #dynamic directive.
#synthesize tells the compiler to create those accessors for you (getter and setter)
#property tells the compiler that the accessors will be created, and that can be accessed with the dot notation or [object message]
I see some examples sometimes would declare a property as well as variable other times they do not .e.g. some time I see code like this
#interface Test : NSObject
{
UIProgressView* _progressView;
}
#property (nonatomic,retain)UIProgressView* progressView;
#end
at other times I will come across
#interface Test : NSObject
#property (nonatomic,retain)UIProgressView* progressView;
#end
Why what are the reasons ? I am learning and almost always use property and variable both.
I have used UIProgressView just as example.
Using ivars instead properties is only useful if you want #protected access (access from subclasses only), or support the old runtime (which required both).
It depends whether the property is synthesized against an iVar or derived in some other way (or against another iVar).
IF we have an instance of the class - i.e:
Test *myTest = [[Test alloc] init];
Then basically the property declaration
#property (nonatomic,retain)UIProgressView* progressView;
is telling anyone interested in using the interface that they can access the following two functions on an instance of this class:
[myTest progressBar];
[myTest setProgressBar:aProgressBar];
And objective C also lets you use shorthand notation:
myTest.progressBar =
xxx = myTest.progressBar
which does exactly the same thing.
It is not necessary for these two methods to be implemented via an iVar of the same name as the property, or even via an iVar at all (they could do even do a database fetch or derive the value).
If you #synthesize the property (which means you want the precompiler to generate the above methods for you) and don't explicitly specify an iVar on the #synthesize directive, then the methods described above will automatically be generated (due to the synthesize method) to set or get the value to/from an iVar of the same name as the property (and the implementation will include retain/release logic depending on the property directive.
If you don't #synthesize the property then you provide your own implementation and it can be anything you want. It is also possible to #synthesize the property but include a directive to use a different iVar in the method definition:
#synthesize progressBar=someOtheriVar;
in which case you will not see an iVar of the same name as the property in the header file either.
I've looked through a bunch of posts on this subject. Maybe I didn't run across "the one" and someone will point me in that direction. The question is simple and probably has a simple answer.
If you have two ivars, say, "public_ivar" and "private_ivar", where/how should you declare them so that what is public is public and what is private is not exposed in any way to anyone looking at the header file?
Same question in the case of "public_method" and "private_method".
I like clean header files (in other languages) that only expose the methods and ivars I want someone else to see. You should be able to publish your header file and not run into the danger of someone accessing something they are not supposed to. How do you do that in objective-C.
For example, let's say that I decide that I need to use an ivar to keep track of some data, a counter or somthing like that, between various class methods that all need access to this information. If that ivar is declared conventionally in the header under #interface its existence is publicly advertised and it is usable by anyone creating an instance of the class. The ideal scenario would be that this ivar would not be visible at all outside of the class implementation.
You can declare instance variables or declared properties in a class extension. Since a class extension is declared in an implementation file (i.e., not a header file), they won’t be visible to someone inspecting the header file. For instance, in the header file:
#interface SomeClass : NSObject
#end
and in the implementation file:
#interface SomeClass ()
#property (nonatomic, assign) int privateInt;
#end
#implementation SomeClass
#synthesize privateInt;
…
#end
or
#interface SomeClass () {
int privateInt;
}
#end
#implementation SomeClass
…
#end
Note that there’s nothing preventing access to private/class extension instance variables (or the accessor methods for properties declared in a class extension) during runtime. I’ve written a rather detailed post about this as an answer to another question on Stack Overflow: Does a private #property create an #private instance variable?
Edit: Instance variables in class extensions were presented in WWDC 2010 session 144.
Edit: "Using the Clang/LLVM 2.0 compiler, you can also declare properties and instance variables in a class extension."
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocCategories.html#//apple_ref/doc/uid/TP30001163-CH20-SW1
Use class extensions to add to a class in your implementation file. A class extension is basically an unnamed category with a few bonuses: properties declared in it can be synthesized and anything declared in it must be in the main implementation, so the compiler can check to make sure you didn't miss an implementation. You must put the class extension before your implementation. You can't add instance variables directly in a class extension, but you can add properties. When you synthesize accessors for properties which don't have corresponding instance variables, the new runtime (os x 10.5 and later and all versions of iOS, I believe) will create the instance variables automatically. This means you can't create your own accessors, however, unless you put the instance variable in your header. Private methods can be added to the class extension without restriction, but as Anomie noted, it is technically possible to use them if you know what they are called, and with class-dump, nothing is safe.
Example usage of a class extension:
#interface MyClass ()
#property (retain) id privateIvar;
#property (readwrite) id readonlyProperty; // bonus! class extensions can be used to make a property that is publicly readonly and privately readwrite
- (void)privateMethod;
#end
#implementation MyClass
#synthesize privateIvar; // the runtime will create the actual ivar, and we just access it through the property
- (void)privateMethod {
...
}
...
Another way of creating "instance variables" without putting them in the header or using a property is to use associative references, which add data to an object at runtime. They aren't technically the same as instance variables, and the syntax for them is more complex. Since they also require the new runtime, there are only two reasons you would ever really want to use them: you want to add an instance variable in a category (outside the scope of this question) or you need it to be really really private. An associative reference doesn't create any methods or add to the class's definition in the compiled code, so if you don't create wrappers for them it is impossible to find out about them without asking the object after you add the data. See the bottom of the page I linked for a complete usage example.
You can use #private to specify that ivars are private. There is no way to make a method private, however. Even if the method is not listed in the header file, if someone knows the name and arguments they can call it.
First off, please forgive the stupidness of this question but Im not from a C/C++ background. I'm a little unclear about what the difference in roles between the .h and .m files when it comes to properties.
I understand the concept of interfaces, and I see that in part the .h file is an interface for the implementation, but what I am not clear on is this:
Why are properties/methods defined outside of the {} braces?
What am i defining in the braces when I write something like this:
IBOutlet UITextField *numberField;
Is this a field definition in an interface?
When I am adding the #Property lines to the .h files are these actual implementations of a n auto property or just an interface blueprint? If so is the #syntesis the actual implementation?
I guess my biggest confusion seems to be that if I want a property I'm defining what I need in three different places (1) in the interfaces braces, (2) as #property outside the braces and (3) with #synthesis in the .m file. This seems long winded, but its fine if I can work out what these three parts do.
Cheers, Chris.
I'll answer your questions below, but perhaps the best way to learn this stuff is to read some user-friendly notes intended for folks new to the language, such as the Learn Objective-C tutorial over at cocoadevcentral.
An example
I'd like to help answer your questions with an example (I love learning by example). Let's say you're a teacher writing a program that asks students a particular yes/no question, and keeps track of how many get it correct and how many students it has asked.
Here is a possible interface for this class:
#interface Question : NSObject {
NSString* questionStr;
int numTimesAsked;
int numCorrectAnswers;
}
#property (nonatomic, retain) NSString* questionStr;
#property (nonatomic, readonly) int numTimesAsked;
#property (nonatomic) int numCorrectAnswers;
#property (nonatomic) int numWrongAnswers;
- addAnswerWithTruthValue: (BOOL) isCorrect;
#end
The three variables inside the braces are instance variables, and every instance of your class will have its own values for each of those variables. Everything outside the braces but before #end is a declaration of a method (including the #property declarations).
(Side note: for many objects, it's useful to have retain properties, since you want to avoid the overhead of copying the object, and make sure it isn't released while you're using it. It's legal to retain an NSString as in this example, but it is often considered good practice to use copy instead of retain since an NSString* might actually point to an NSMutableString object, which may later change when your code expects it to stay the same.)
What #property does
When you declare a #property, you're doing two things:
Declaring a setter and getter method in the class's interface, and
Indicating how the setter and getter behave.
For the first one, it's enough to know that this line:
#property (nonatomic, retain) NSString* questionStr;
is basically the same as this:
- (NSString*) questionStr; // getter
- (void) setQuestionStr: (NSString) newQuestionStr; // setter
in the header. You literally are declaring those two methods; you can call them directly, or use the dot notation as a shortcut to call them for you.
The "basically" part in "basically the same" is the extra info given by keywords like nonatomic and retain.
The nonatomic keyword indicates that they're not necessarily thread-safe. The common retain keyword indicates that the object retains any value that's set, and releases previous values as they're let go.
For example:
// The correct answer to both questions is objectively YES.
Question* myQuestion = [[Question alloc] init];
NSString* question1 = [[NSString alloc] initWithString:#"Is pizza tasty?"];
// question1 has retain count of 1, from the call to alloc
myQuestion.questionStr = question1;
// question1 now has a retain count of 2
NSString* question2 = [[NSString alloc] initWithString:#"Free iPhone?"];
myQuestion.questionStr = question2;
// question1 has a retain count of 1, and question2 has retain count of 2
If the #property declaration for questionStr had been assign instead, then all the myQuestion.questionStr = statements would not have made any changes at all to the retain counts.
You can read a little more about properties here.
What IBOutlet and IBAction do
These are basically no-op words which act only as a way to tell Interface Builder which pieces of the header file to pay attention to. IBOutlet literally becomes an empty string when the compiler looks at it, and IBAction becomes the void return value. We do need them to work with Interface Builder, though, so they are important -- just not to the compiler.
Quick note on C structs and arrow vs dot notation
By the way, the data part of an Objective-C object is very similar to a C struct. If you have a pointer to a C struct, you can use arrow notation -> to refer to a specific part of the struct, like this:
struct MyStructType {
int i;
BOOL b;
};
struct MyStructType* myStruct;
myStruct->i = 3;
myStruct->b = TRUE; // or YES in Objective-C.
This same syntax works the same way in Objective-C:
Question* question = [[Question alloc] init];
question->questionStr = #"Is this a long answer?"; // YES
But when you do this, there is no method call happening behind the scenes, unlike the dot notation. With the dot notation, you're calling the setter (or getter if there's no = afterwards), and these two lines are the same:
question.questionStr = #"Chocolate?";
[question setQuestionStr:#"Chocolate?"];
It's often a good idea to avoid the arrow notation in favor of the dot notation, since the dot notation lets you enforce valid state -- for example, that the pointers your class has are always retained. You can even disallow others from using the arrow notation by declaring your instance variables as #private; they can still use the getter and setter to access it, if you declare a #property for it.
What #synthesize does
Now, when you get around to actually implementing your class, #synthesize says something like "make sure the getter and setter get implemented for this property." It does not say "implement both of these for me," because the compiler is polite enough to check for your own implementation first, and only fill in the pieces you've missed. You don't have to use #synthesize at all, even if you use #property out the wazoo -- you could always just provide your implementations for your setters and getters, if you're into that sort of thing.
You probably noticed in the Question interface above that there's a property which is not an instance variable (numWrongAnswers), which is fine because you're just declaring methods. In the example code here, you can see how this actually works:
#implementation Question
#synthesize questionStr, numTimesAsked, numCorrectAnswers;
- (void) setNumCorrectAnswers: (int) newCorrectAnswers {
// We assume the # increases, and represents new answers.
int numNew = newCorrectAnswers - numCorrectAnswers;
numTimesAsked += numNew;
numCorrectAnswers = newCorrectAnswers;
}
- (int) numWrongAnswers {
return numTimesAsked - numCorrectAnswers;
}
- (void) setNumWrongAnswers: (int) newWrongAnswers {
int numNew = newWrongAnswers - self.numWrongAnswers;
numTimesAsked += numNew;
}
- (void) addAnswerWithTruthValue: (BOOL) isCorrect {
if (isCorrect) {
self.numCorrectAnswers++;
} else {
self.numWrongAnswers++;
}
}
#end
One thing that's happening here is we're faking an instance variable called numWrongAnswers, which would be redundant information if we stored it in the class. Since we know numWrongAnswers + numCorrectAnswers = numTimesAsked at all times, we only need to store any two of these three data points, and we can always think in terms of the other one by using the two values we do know. The point here is to understand that a #property declaration is really just about declaring a setter and getter method, which usually corresponds to an actual instance variable -- but not always. The #synthesize keyword by default does correspond to an actual instance variable, so that it's easy for the compiler to fill in the implementation for you.
Reasons to have separate .h and .m files
By the way, the whole point of declaring methods in one file (the .h header file) and defining their implementation in another (the .m or methods file) is to help decouple the code. For example, if you only update one .m file in your project, you don't have to recompile the other .m files, since their object code will remain the same -- this saves time. Another advantage is that you can use a library that includes only header files and pre-compiled object code, or even dynamic libraries where you need the header file so the compiler is aware of which methods exist, but those methods aren't even linked in with your executable file. These advantages are hard to appreciate when you first start coding, but just the logical breakdown and encapsulation of implementation becomes useful after a short while.
I hope that's helpful!
methods are defined outside of the braces since the braces are meant to encapsulate the state of the object which can be argued does not include the instance or class methods.
What you are defining in the braces are instance variables that can be referenced as self.ivar
The #property and #synthesize directives simply setup accessors for you instance variables so you can set them by doing self.ivar = someVar. So in other words it sets up the "dot syntax" for you to use.
and to answer your finale question: To define a property or instance variable simply declare it in your .h file as a variable inside the braces. To setup accessor methods on that same property you need to do BOTH #property and #synthesize.
Well that is just Objective C syntax, methods and #property outside {} and variables inside {}.
#property is the way of telling that you are going to write getter and setters (kind of enforcing it), but you can write getter/setter without setting them #property. #property is in .h file because its declaration. And why it is outside {}, well as i said before its just the syntax, what we can do?
#synthesis will in actual implement getter and setters, if you dont synthesis but you have set them #property, you have to implement those getter and setters by your hand. And #synthesis is in .m file because its implementation.
Something more for you to read on this subject can be find here.
http://theocacao.com/document.page/510
The variables inside the brackets define the physical structure of your class. Those are the actual instance variables that store information.
The stuff outside the brackets make up the class's interface — methods and properties. A property in and of itself does not reserve any storage space or affect any variable — it just declares a generic interface for accessing something. Remember that a property doesn't have to have an underlying instance variable — for example, the totalPrice property in a ShoppingCart class might dynamically sum the prices of all the items in the cart.
Inside the implementation file, you tell the class how to actually do its work. For methods, obviously, you just supply an implementation. For a property, you can either provide accessor implementations yourself or ask it to synthesize accessors for an instance variable.