I'm looking for the syntax of the getter/setter. Which is the setter and which is the getter??
Is the readwrite attribute the getter?
Is the assign the setter?
#interface SomeClass : NSObject
{
NSString *str;
NSDate *date;
}
#property (readwrite, assign) NSString *str;
#property (readwrite, assign) NSDate *date;
Neither is the getter or the setter. readwrite controls whether a set method is generated or just a getter, and assign specifies the memory management scheme (in this case, the variables are not retained, which is probably a mistake).
For the full property declaration syntax, you can take a look at the relevant docs.
You should check out this page, it will explain things.
readwrite = the property can be read and written
assign = this is a property that doesn't need to be ref counted. (the alternative is 'retain,' which means that values of this property are retained when set and released when overwritten.
Neither. The code you posted is an interface declaration; getters and setters go in an #implementation context, and are usually created using the #synthesize directive, as in
#synthesize str;
#synthesize date;
There are a number of attributes that can go after a property declaration. In this case, the readwrite specifies that the value of the property can be set (using the someObject.str = #"foo" syntax); the opposite is readonly, which means that the value of the property cannot be set. assign—as opposed to copy or retain—means that the property's value gets set directly, whereas the latter two create a copy of the value and retain the value, respectively.
The getter and setter are two methods that are automatically created when you use #property. By default, the getter will have the same name as the property, the the setter will have the name prefixed with set and suffixed with :; for instance, for the property str, you would be able to call [someobj str] to get the str property, and [someobj setStr: somestr].
The readwrite and assign attributes provide some information about how this getter and setter should be defined, if you use #synthesize to create the definitions for you. readwrite simply says that you are allowed to set the property, and assign says how the property will be set. See the documentation for more info.
Related
In Objective-C, should a wrapper property be set to weak? By wrapper property I mean that the property is a wrapper of another property.
e.g.
- (Prop *)prop {
return self.obj.prop; //wrapper method for another property
}
#property (nonatomic, readonly, weak) Prop *prop; // weak or strong?
"correct" in this case is a matter of convention and preference as Objective-C properties do support this pattern. Accessing a property does call a method which is either generated, synthesized or manually coded.
I'll stay out of whether it's "correct" or not.
Since your property only returns the value of a different property, then you don't need to specify strong or weak as they are meaningless.
In the public header:
# myclass.h
#interface MyClass
#property (nonatomic, readonly) OtherClass *someProperty;
#end
In the implementation:
# myclass.m
#implementation MyClass
- (OtherClass *)someProperty
{
return self.someObject.otherProperty;
}
Using a property is not necessarily the best way to go. It shouldn't really be weak or strong as it will never be set. You are never going to create a readwrite counterpart and generate an instance variable / accessor methods.
So, it's better to represent this as a simple method in the header file. It's more accurate as a description of the interface offered.
I'm trying to get the property attributes of an object with the property_getAttributes() runtime function. Some properties are set read-only. But the problem comes when I try to make the difference between retain/strong, weak and assign properties. e.g.:
Let's say we have:
#interface MyObject : NSObject
#property (assign, readonly) NSObject *prop1;
#property (strong, readonly) NSObject *prop2;
#property (weak, readonly) NSObject *prop3;
#end
We get the property list and print
int outCount;
objc_property_t *properties = class_copyPropertyList([MyObject class], &outCount);
for(i = 0; i < outCount; i++) {
objc_property_t property = properties[i];
const char *c_attributes = property_getAttributes(property);
printf("%s", c_attributes);
}
free(properties);
The result is:
T#"NSObject",R,V_prop1
T#"NSObject",R,V_prop2
T#"NSObject",R,V_prop3
...so no specific code for weak, strong/retain, assign properties when they are read-only :(
The question is: is there any other way to know if the property is weak, strong/retain, assign?
I haven't tried your code, but according to
https://developer.apple.com/library/mac/documentation/cocoa/conceptual/objcruntimeguide/articles/ocrtpropertyintrospection.html
R The property is read-only (readonly)
C The property is a copy of the value last assigned (copy).
& The property is a reference to the value last assigned (retain).
N The property is non-atomic (nonatomic).
G The property defines a custom getter selector name. The name follows the G (for example, GcustomGetter,).
S The property defines a custom setter selector name. The name follows the S (for example, ScustomSetter:,).
D The property is dynamic (#dynamic).
W The property is a weak reference (__weak).
P The property is eligible for garbage collection.
t Specifies the type using old-style encoding.
To answer your question quickly, the answer is no.
The issue here is that memory management semantics for properties (those are assign, unsafe_unretained, strong, weak, copy in ARC and assign, retain, copy in MRC) only have any application in automatically generated setter code. Should you write your own setter for the property you are of course encouraged to implement the semantic yourself (but not required). The getter of these properties are not modified at all by these property attributes. Consider this code:
#interface FooBar ()
#property (nonatomic, strong, readonly) NSString* foobar;
#end
#implementation FooBar
- (NSString*) foobar {
return [NSString stringWithFormat:#"aString"];
}
In these situations the caller will make a either a strong or weak reference and the return value must live for at least as long as the calling code needs to complete the statement. In the case of a weak reference it will go to nil afterwards since a property with strong does not guarantee that the referenced object will be kept for you. Ultimately, memory management on readonly properties are nothing more than a placebo that end up there mostly by either habit or style #property (nonatomic, readonly) ... is perfectly legal, but confusing when we are used to encountering a memory attribute in the property declaration.
PS: There's another function in the runtime called property_copyAttributeList which I find much easier for parsing this information (it uses structs to break up the components for you).
I was wondering what the point of #property and #synthesise were. At the moment I use the following to declare something:
//Class.m
#import "Class.h"
CCNode *node;
#implementation
//init, etc..
But I have seen others use:
#property (nonatomic, etc..) CCNode* node;
#synthesise (nonatomic, etc..) node;
//I am not too sure on how this type of declaration works, please correct me on how it's done.
They both seem to work in the same way, what are the advantages of the #property and #synthesise way? Do they do different things, if so, what?
#property and #synthesize are two objective C keyword that allow you to easily create your properties and therefore avoid to write by hand getters and setters methods of the property.
The #property define the property itself, should be placed in the header file and can get some attributes (as for example : strong, nonatomic, retain assign, copy), the #synthesize should be placed into the implementation file and tell the compiler to generate the body of getter and setter method.
These two keyword are extremely useful when coupled with the right use of their attributes, because they take care of the generation of the property code and most of all they take care of the memory management of the property.
#property - create the declaration of your getter and setter.
#synthesize - provide the definition of getter and setter based upon the parameters which are passed inside property.
Check this out, there are a lot more details about the same present there - https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html
on using #property the compiler will take care of declaring getter and setter methods based on readonly and readwrite
readonly -> getterMethod
readwrite -> both setter and getter method
on using #synthesize the compiler will take care of defining getter and setter methods
If you have an instance variable (ivar) in your class, you can't access it from other classes usually. So you have to make public accessor methods (getters and setters). They look something like this:
Setter:
- (void)setMyVariable:(SomeClass *)newValue {
if (newValue != myVariable) {
[myVariable release];
myVariable = [newValue retain];
}
}
Getter:
- (SomeClass *)myVariable {
return myVariable;
}
This was the way you had to do it before Objective-C 2.0. Now you can use #property and #synthesize to speed this up. It's basically just a shortcut.
In the header you use #property to define what kind of setters you want. Should the setter retain the passed value (like in my example) or copy or just assign?
And in the implementation you just write #synthesize to make the compiler include the automatically created getters and setters at that position. Usually at the top of your implementation.
My feeling is that all iVars should have an associated underscore synthesised property (using an _iVar prevents accidental direct access), and all access to the iVars, apart from init and dealloc methods, should via the property.
IMHO the big win is memory management - it's safer and much easier as there is no need to remember which iVars have been retained.
And think of how much work is required to code an accessor - 4 lines for getter and 2 for a setter.
At some point in the future #synthesize is likely to be optional, so all you'll need is the #property.
I don't know assembler well enough to understand so complicated code as Assembly for whole project, but I noticed that if I put strong attribute to the property, a _objc_storeStrong call shows up near the line in my setter where I change my properly;
#interface ClassName : NSObject
#property (strong, nonatomic) NSSet *mySet;
#end
#implementation ClassName
#synthesize mySet;
-(void)setMySet:(NSSet *)newMySet
{
mySet = newMySet;
//do stuff
}
#end
So? am I right? Do the ARC compiler automatically determines whether to retain or assign in overridden class depending on property attributes?
In short, yes. Because you set the property as strong, it will be retained by the object. If you declare the property as weak, the implied (synthesized) variable is __weak NSSet *mySet and that won't retain the object, but it will be a auto-zeroing pointer.
I have a property like this:
#property (nonatomic, strong) IBOutlet UIImageView *backgroundImageHolder;
I want to adjust the setter, and XCode fills out the method signature like this:
-(void)setBackgroundImageHolder:(UIImageView *)backgroundImageHolder {
However, to actually do anything in the method, I must change the parameter backgroundImageHolder to something like backgroundImageHolderIn. Is there any way to avoid this? Is there any way to set the iVar without reinvoking the setter (causing an endless loop), or just referring to the parameter again?
I just tried:
self->backgroundImageHolder = backgroundImageHolder;
but the compiler warns me anyway.
Note: I am using the automagically generated iVar that the compiler makes for the property, but by default its name is the same.
You can give tell the compiler how to name the generated ivar:
#synthesize propertyName = iVarName;
If there actually exists an ivar named iVarName that one is used. If it doesn't exist the compiler creates it for you.
Like:
#synthesize backgroundImageHolder = myBackgroundImageHolder;
Now you can access the instance variable myBackgroundImageHolder. You don't need to declare it in the interface first.
Well, the conflicting parameter name seems to be pretty well covered by now. Basically, you have to either:
Rename the incoming argument
Rename the synthesized iVar
Once you have a method argument that differs from the iVar you're attempting to set, you have everything you need to write a custom setter. To avoid the infinite loop, you have to not call the setter you're currently implementing, whether it be via dot syntax or method brace syntax. Instead, refer directly to the backing iVar. You'll need to take care to manually implement the memory management semantics you declared in the property though (assign vs. retain, etc.):
// Backed by _myProperty iVar.
- (void)setMyProperty:(NSInteger)myProperty {
// Insert custom code here...
[self setMyProperty:myProperty]; // Obviously bad.
self.myProperty = myProperty; // Less obviously bad (thanks dot syntax)
// but semantically identical to the previous line.
_myProperty = myProperty // Good, (assuming assign semantics).
}
Compiler warns you because when you declare #property it creates instance variable with exact same name as a property (and as a parameter of a setter method). One way to avoid it is to create differently named instance variable and then pair it with property using #synthesize like this:
// .h
#interface Foo : NSObject {
IBOutlet UIImageView *myfooImageView;
}
#property (nonatomic, retain) UIImageView *publicFooImageView;
// .m
#implementation Foo
#synthesize publicFooImageView=myfooImageView;
#end
The clearest thing to do would be this:
In your header, define an iVar for backgroundImageHolder like so
#interface Something : NSObject
{
IBOutlet UIImageView *_backgroundImageHolder
}
Notice the leading underscore.
Then in your .m file, use either the synthesize call like so:
#synthesize backgroundImageHolder=_backgroundImageHolder;
or just define the getter and setter methods yourself: Then you are able to access the ivar via "_backgroundImageHolder" without any danger of accidentally calling the setter again.