When to use attributes and What is the purpose of each attribute?
Some attributes:
readonly - use if you don't want a setter
retain - use if you want values assigned to your property to be retained
copy - use if you want values assigned to your property to be copied.
assign - use if you want new values to be assigned with no retain or copy.
nonatomic - use to disable the mechanism that makes property access atomic. An atomic property is guaranteed to give you a pointer to a real object that still exists or nil. In a multithreaded environment, a nonatomic property could give you an object that has already been deallocated.
Related
In Objective C, if I have a class, within the class a method that creates a string using some convenience method and set the property NSString pointer to the newly created string. In this case, because the string is created using convenience method, it will have one owner which is the autorelease pool. When I assign the string to the property NSString pointer, will the compiler set the property as an owner to that string by inserting a retain call?
I think it should. Otherwise, when the autorelease pool is drained, the string will be released. However, if the object of the class still lives outside the autorelease pool, the property will point to memory that is already released, which causes a premature deallocation issue. In this case, there should be a retain call to set the object as a new owner to the string. Am I right on this?
The phrase "assign the string to the property NSString pointer" is a bit ambiguous. If you use the property setter either as a method invocation or with dot syntax the memory management specified or defaulted for the property will be used. If you assign directly to the underlying pointer, then you are bypassing the property attributes and the retain state will remain whatever it was before assignment.
How would you return an object from a method, so it is read-only for the caller?
Please note that this isn't a property that can be simply set to read-only when it's getter is declared
i.e #property(nonatomic,retain,readonly) NSDate* pub_date;
For example:
-(SomeClass*)getObject
{
SomeClass* object = [[SomeClass alloc] init];
//Don't allow writing to 'object'
return object;
}
Thanks.
Short answer: there's no simple way of doing this.
Longer answer: Apple's framework defines a sort of standard for its collection classes where the immutable collection is the base class and the mutable collection is the inheriting class. So, for example, NSMutableArray inherits from NSArray. You can follow that standard, and have methods that return MyClass to clients while using MyMutableClass inside them. Technically the client can still send the mutating messages, of course, but IMHO that's not a big risk (after all, the client doesn't know your implementation details).
There are other, more complicated options - you can use pointer swizzling, or subclass and override all mutating methods, or simply copy the mutable class into an immutable counterpart (that's not complicated but may incur a performance hit). But for best results you should probably follow Apple's example.
It depends what the object is. If it has a mutable / immutable pair (like NSString/ NSMutableString) then your getter method can return the immutable version.
Otherwise, you can't control the behaviour of other objects - once you've returned an object, there is no control over it from the object that originally provided it.
If you are concerned that another object may alter an object returned from a getter, and thereby amend the property held within the original object, then you should return a copy of the object instead.
Example:
Object A has a mutable string property, object B asks for this mutable string, the getter directly returns the instance variable backing the property.
Object B then changes the string - the property of object A has also been amended because both objects have a pointer to the same mutable string.
In this case, you would return a copy of the object rather than the object itself. If your object is a custom one, you must implement the NSCopying protocol to allow this.
A further note - declaring a property as read only simply means that no setter accessor will be generated - i.e. objectA.property = newValue; will result in a compiler error.
Is there a way in Objective-C to set a property value of a class instance X without directly invoking the setter, but just somehow specifying the property name ?
I have a NSDictionary in which the keys are the property names and the values are the values to assign.
Now I just would like to iterate my NSDictionary and set the property of the instance X by just specifying the key.
I hope it is clear...
thanks
You can do this using Key Value Coding. Just use the setValue:forKey: and valueForKey: methods to set and get properties. Behind the scenes those will use the setters if available, but they also can access ivars directly, if there are no accessors.
I have seen code like that in the Application delegate in iPhone project for example.
what is the variable with the underscore means? can I use it as setter and getter for the variable?
also when releasing the variable should I use:
[variable release];
or
[_variable release];
Thanks.
In some coding conventions the underscore before instance variables is used to be able to quickly differentiate them from other variables. It also helps avoid naming conflicts with local variables in methods and subclass methods.
#synthesize variable = _variable
Creates a setter and getter that set/get the variable you set it to in this case _variable. So outside access uses code like object.variable which is really just returning _variable. however the class usually uses the _variable internally.
#synthesize variable = _variable;
The property name is "variable" and the instance variable that backs it up is named "_variable". You should use the accessors -variable and -setVariable: rather than accessing the ivar directly, except in -init and -dealloc, where you'd use _variable.
In your example variable is a property and _variable is an instance variable. For simplicity sake we can say that by synthesizing you are essentially instructing that the property ( in our case variable) will use the instance variable ( in our case _variable) for storing and retrieving values. What you are really doing is instructing the compiler to create implementations that match the specification given in the property declaration.
The suggested way of releasing when you are using a property will be to just assign it nil. This would essentially release the object and also set the instance variable to nil instead of being a dangling pointer.
If you were not using property then you can call the release on the instance variable and then ideally you want to set it to nil.
What exactly is the difference between retain and copy? what is its significance on reference counting?
I know that when an object is allocated using alloc/retain, reference count goes up by one.
so how about using copy?
Another question relating to this is, the difference between using
#property(nonatomic, retain) and #property(nonatomic,copy)?
retain -- is done on the created object, it just increase the reference count.
copy -- create a new object
Answering your question to the best of my knowledge.
First, What exactly is the difference between retain and copy? what is its significance on reference counting?
retain - "Specifies that retain should be invoked on the object upon assignment. ... The previous value is sent a release message." So you can imagine assigning an NSString instance (which is an object and which you probably want to retain). So the retain count goes up by 1.
copy - "Specifies that a copy of the object should be used for assignment. ... The previous value is sent a release message." Basically same as retain, but sending -copy rather than -retain. if i remember correctly the count will go up by 1 too.
ok, now going into more detail.
Property attributes are special keywords to tell compiler how to generate the getters and setters. Here you specify two property attributes: nonatomic, which tells the compiler not to worry about multithreading, and retain, which tells the compiler to retain the passed-in variable before setting the instance variable.
In other situations, you might want to use the “assign” property attribute instead of retain, which tells the compiler NOT! to retain the passed-in variable. Or perhaps the “copy” property attribute, which makes a copy of the passed-in variable before setting.
I hope that helps. I found another post in here that might help you too.
Objective C - Assign, Copy, Retain
Cheers!
Jose
Generally speaking, copy creates a new object which has the same value with the original object, and sets the reference count of the new created object to 1 (By the way, reference count of the original object is not affected).
However, copy is equivalent to retain for immutable object, which JUST increate the reference count of the original object by 1.