Objective-C property attributes best practices - objective-c

After multiple searches and reads about property attributes, I still can't understand them completely and create a reflex of using them correctly.
I have multiple questions:
1) What does a default attribute mean?
As I understood, not specifying an attribute in a "group", the default one is used, so this:
#property NSString *string;
is atomic, right?
By this logic, this article says that strong and assign are defaults, so if I have:
#property (nonatomic) NSString *string;
is the string property strong or assign?
How are the available attributes "grouped"? Or as Xcode words this, what attributes are mutually exclusive?
2) Are there any generic rules that one should follow?
For example, I saw one comment that said that you should use copy for classes with mutable variants like NSString, NSArray.
And another one that said that you should use assign for C objects.
So, is it a good idea to always use:
#property (copy, nonatomic) NSString *string;
#property (assign, nonatomic) CGFloat float;
?
What other standard practices exist for property attributes?
3) What problems could arise if I use "wrong" attributes? What if I just use nonatomic for all the properties in a project?

1a) The default attributes for a property are atomic, and strong (for an object pointer) or assign (for a primitive type), and readwrite. This assumes an all ARC project.
So #property NSString *string; is the same as #property (atomic, strong, readwrite) NSString *string;. #property int value; is the same as #property (atomic, assign, readwrite) int value;.
1b) Attributes are grouped as follows:
atomic/nonatomic
strong/weak/assign/copy
readwrite/readonly
Pick one and only one from each of those three groups.
Actually, the latest Objective-C adds support for nullable/nonnull with the default being nullable.
2) General rules are as you say.
Object pointers should usually be strong.
Primitive types should be assign.
weak should be used in child/parent references to avoid reference cycles. Typically the parent has a strong reference to its children and the children have a weak reference to their parent. Delegates are typically weak for the same reason.
copy is typically used for NSString, NSArray, NSDictionary, etc. to avoid issues when they are assigned the mutable variant. This avoids the problem of the value being changed unexpectedly.
There's a big "gotcha" using copy with NSMutableString, NSMutableArray, etc. because when you assign the mutable value to the property, the copy attribute results in the copy method being called which gives back a non-mutable copy of the original value. The solution is to override the setter method to call mutableCopy.
3) Using the wrong attribute could have serious problems depending on the needs of the property and the attribute being used.
Using assign instead of strong for an object pointer is probably the worst mistake. It can lead to app crashes due to trying to access deallocated objects.
Using nonatomic instead of atomic on a property that will be accessed concurrently on multiple threads may lead to really hard to find bugs and/or crashes.
Using strong instead of copy for NSString or NSArray (and other collections) can possibly lead to subtle and hard to find bugs if mutable variants were assigned to the property and other code later modifies those values.

#rmaddy's answer is a good one.
I would add the following.
If you are creating (or have inherited) classes that interoperate with Swift, it is very useful to include nullable or nonnull property attributes. If you add it in any part of a header file, you will need to specify it for all parts of the header file (compiler warnings will help you). It's even quite useful for Objective-C callers to know from the method signature what may and may not be a nil value.
Another property of note is class. You can add a property to the class.
Adding these two items together, and if you are implementing a singleton,
+ (MyClass *)sharedInstance;
it's quite useful to define it as a property:
#property (class, nonatomic, nonnull, readonly) MyClass *sharedInstance;
(In which case you are required to add a backing variable for it as described in this article)
This will let you access the shared instance via dot notation.
[MyClass.sharedInstance showMeTheMoney:YES];
And in Swift, the rather annoying
MyClass.sharedInstance()?.showMeTheMoney(true)
turns into
MyClass.sharedInstance.showMeTheMoney(true)
‡ maybe it's just 3 characters to you, but it keeps my head from exploding mid-day.
Edit:
I would add, try out
+ (instancetype)shared;
This 1) shortens the naming to concur with modern Swift convention, and 2) removes the hardcoded type value of a (MyClass *).

Related

How to choose the attributes of a #property in a nutshell? [duplicate]

This question already has answers here:
Objective-C declared #property attributes (nonatomic, copy, strong, weak)
(4 answers)
Closed 9 years ago.
How to quickly know which attribute to add to a #property ?
I got it for #property (strong) and #property (weak), I think : strong if the class "owns" the referred-to instance ; weak if it is just a reference to an object whose existence is not managed to our current class.
If the property is created by dragging-and-dropping from Interface Builder, sometimes there is the cryptic unretain_unsafe or so. It sounds so complicated to me, but I believe Xcode knows what it does...
I also kind of understand that retain, assign are kind of deprecated...
And that it is better (compulsory) to use copy for NSString attributes...
But what if I want to have a #property to an int or an enum ?
Shall I choose the weak attribute if my #property points to a singleton ?
You see : so many questions for theses attributes !
I thought it would be nice to have a short and clear explanation of these attributes as some members here do :)
A few notes in no particular order
weak has the additional features of being nil-ed out when the referred-to object is deallocated, so you are never left with a dangling pointer to garbage
It is not compulsory to use copy semantics with an NSString property, but it is highly recommended. While NSString is immutable, your property might be set to a mutable string subclass, so if you don't want it changing out from under you, you should use copy
The rule of thumb for scalar property types is pretty simple: they are not reference counted, so neither strong nor weak applies. But they can be readonly or readwrite, depending on what you need.

What is the correct way to declare a readonly property for ios using ARC

I am new to iOS development in general and have never dealt with manual reference counting (retain, release, autorelease). As such I don't have a good understanding of what magic ARC is performing.
I thought I understood until I was asked what type of ownership (weak, strong, assign, etc) should be given to a readonly property pointing at an object, such as:
#property (readonly,nonatomic) NSString* name;
I read here
Questions about a readonly #property in ARC that leaving off the strong/weak won't actually compile unless you specify a backing variable when you #synthesize the property; I just so happened to be specifying a backing ivar like this:
#synthesize name = _name;
Now I understand that the default 'lifetime qualifier' of a variable is strong, from here: http://developer.apple.com/library/ios/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html#//apple_ref/doc/uid/TP40011226-CH1-SW4
So to cut a long story short - I am indirectly defining my property as (readonly,nonatomic,strong) as the _name ivar is implicitly declared as __strong.
I have a few questions:
Is strong the correct lifetime qualifier to use? I assume that it is, otherwise the object backing my NSString* wouldn't be owned anywhere and would thus be freed automatically (coming from Java land this makes sense as all references are strong by default).
Are there any other modifiers which make sense in this situation, such as copy or assign?
Does declaring the property as (readonly,nonatomic,strong) and (readonly,nonatomic) make any difference to the code which consumes the property? eg. does declaring it without the strong keyword cause the object pointer to be stored as __unsafe_unretained where the strong property would be stored in a __strong pointer?
Thanks!
EDIT
So as I understand now, the following applies to readonly properties:
For non-NSObject* types (int, float, void*, etc) use (readonly, assign).
For object pointers, use (readonly, strong) or (readonly, copy) - these function the same for readonly properties but you may want the copy semantics if you extend/subclass and redeclare the property as readwrite.
For object pointers, (readonly, weak) only makes sense if you are going to be storing an already weak pointer in that property (that pointer must be strong elsewhere or the object will be deallocated).
strong is correct to use if you want to keep a strong (owning) reference to whatever it is that you are pointing to. Usually, you do want strong, but in order to prevent circular references (particularly in parent/child relationships where if the parent points to the child and the child points to the parent, they will never be released) you sometimes need to use weak references. Also, if you want to keep a pointer to an object that you don't own but want it to be valid only as long as it exists, then you want to use a weak pointer because when it gets deallocated by the owner, your pointer will automatically get set to nil and won't be pointing to memory that it shouldn't be.
assign is used with scalar values, and is the default setter. copy makes sense if you want to automatically make a copy of the object and set your pointer to the copy instead of pointing to the original object. It only makes sense to do this if you have a specific need (usually because you don't want the object to mutate on you).
The link that you provided which shows that __strong is the default (and therefore you don't need to specify it) refers to variables and not to declared properties. The default for declared properties is assign so it certainly will make a difference. If you were wanting assign however, it makes no difference whether you specify it or not (other than just to be clear that it is what you wanted).
EDIT: However, as Jacques pointed out, this is changing with LLVM 3.1 and the default is changing from assign to strong. In this case, it makes absolutely no difference whether or not you specify strong and can leave it out if you want. Personally I think that it is good to spell it out (especially since there is a conflict between different versions) so that everyone looking at the code is on the same page. Others may disagree on this point though. :)
I would suggest reading the Declared Properties section of The Objective-C Programming Language here: <document removed by Apple with no direct replacement>.
One additional point: properties can get redeclared from readonly to readwrite. For example, a subclass may make a read-only property from the superclass read-write, similar to how many Cocoa classes have subclasses that add mutability. Likewise, a property may be publicly read-only but the class may redeclare it read-write for internal use in a class extension. So, when the class sets its own property it can take advantage of a synthesized setter that does memory management properly and emits appropriate Key-Value Observing change notifications.
As things currently stand, all of the other attributes of the property have to be consistent. It's conceivable that the compiler could relax this requirement. (Some consider it a bug.) Anyway, that's one reason to declare a readonly property with an ownership attribute like strong, copy, or weak – so that it will match the readwrite redeclaration elsewhere.
With regard to your question 3, are you asking if the ownership qualifier affects code which calls the getter? No, it doesn't.
These 2 lines of code work for me:
.h file:
#property (nonatomic, readonly, copy) NSString *username;
.m file:
#property (nonatomic, readwrite, copy) NSString *username;

Class copies NSArray of other class and owns it distinctly

I want to make sure I understand a key concept of properties and instance variable ownership of a class, in this case using NSArray.
Suppose I pass a reference to an NSArray to another class, and set that class's iVar to it. For example:
First Technique
OtherClass.h
#property (nonatomic, retain) NSArray * otherClassArray;
then:
CurrentClass.m
otherclass.otherClassArray=myArray
Now, even though OtherClass is retaining myArray, if CurrentClass changes myArray then otherclass.otherClassArray will also change, correct?
So, is this the better way to do it, or am I mistaken and the above will do what I'd expect from the following anyway:
Second Technique
CurrentClass.m
otherclass.otherClassArray=[NSArray arrayWithArray:myArray]
Now there is a distinct copy being made so any changes to myArray have no effect on otherClassArray, am I right, or are both of these approaches doing the same thing?
UPDATE: Is there any reason why my second technique above should or should not be used vs. using copy with the property? It would seem that either technique results in a new NSArray that my class owns.
This is exactly why it is generally recommended that properties whose classes have mutable subclasses (most notably, NSString and the various collection classes) be declared as copy:
#property (nonatomic, copy) NSArray * otherClassArray;
Then whenever you set the property, OtherClass will get its own version of the array.
Your second technique has the same result as declaring a copy property, yes, but it should be left up to the property's owner whether it wants a copy or not. To put it another way, the principle of encapsulation demands that client code (CurrentClass) not be responsible for knowing that OtherClass needs to have its own version of the object. It's a matter of design and maintainability.

Simple Properties in Objective-C Classes

I've bene working with Objective-C for a while now, and so far I have never really needed to craft my own classes, properly.
I am a bit confused with the two arguments you can give the #property(a, b) declaration in a header file. When creating outlets to Interface Builder I usually do #property(nonatomic, retain) but I have no idea what this means.
I'm writing a simple class which has a set of properties which will be set from the outside, like [instance setName:#"Bla Bla Bla"]; or I guess like instance.name = #"Bla#" but I would rather the first option.
How would I declare this kind of property on a class?
Thanks in advanced!
Sorry for the n00bish question :-)
The #property parameter gives you a hint on the property behavior:
nonatomic tells you that setting/getting the property value is not atomic (wrt to multiple thread access)
retain tells you the object will be retained by the property (i.e. The receiver will take ownership of the object). The othe options are "copy" (the object is copied using -copy. This is generally the good choice for value objects like NSStrings) and "assign" (the object is just assigned to the property without retaining it. This is generally the good choice for delegates or datasources). These 3 options are only useful for ObjC objects, not simple C type properties.
See http://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocProperties.html for more info.
For your case, you'll likely use:
#property(copy) NSString* name;
Or:
#property(nonatomic, copy) NSString* name;
If you don't need the property setter/getter to be atomic.

Properties and Instance Variables in Objective-C

I'm rather confused about properties and instance variables in Objective-C.
I'm about half-way through Aaron Hillegass's "Cocoa Programming for Mac OS X" and everything is logical. You would declare a class something like this:
#class Something;
#interface MyClass : NSObject {
NSString *name;
NSArray *items;
Something *something;
IBOutlet NSTextField *myTextField;
}
#property (nonatomic, retain) NSString *name;
#property (nonatomic, retain) NSArray *items;
Since other objects need to manipulate our name and items instance variables, we use #property/#synthesize to generate accessors/mutators for them. Within our class, we don't use the accessors/mutators—we just interact with the instance variable directly.
something is just an instance variable that we're going to use in our class, and since no one else needs to use it, we don't create a pair of accessors and mutators for it.
We need to interact with a text field in our UI, so we declare an IBOutlet for it, connect it, and we're done.
All very logical.
However, in the iPhone world, things seem to be different. People declare properties for every single instance variable, declare properties for IBOutlets, and use accessors/mutators to interact with instance variables within the class (e.g. they would write [self setName:#"Test"] rather than name = #"Test").
Why? What is going on? Are these differences iPhone-specific? What are the advantages of declaring properties for all instance variables, declaring properties for IBOutlets, and using accessors/mutators within your own class?
In the iPhone world, there's no garbage collector available. You'll have to carefully manage memory with reference counting. With that in mind, consider the difference between:
name = #"Test";
and
self.name = #"Test";
// which is equivalent to:
[self setName: #"Test"];
If you directly set the instance variable, without prior consideration, you'll lose the reference to the previous value and you can't adjust its retain count (you should have released it manually). If you access it through a property, it'll be handled automatically for you, along with incrementing the retain count of the newly assigned object.
The fundamental concept is not iPhone specific but it becomes crucial in an environment without the garbage collector.
Properties are used to generate accessors for instance variables, there's no magic happening.
You can implement the same accessors by hand.
You can find in Aaron Hillegass's book examples of 3 memory management strategies for member variables. They are assign/copy/retain. You select one of those as required for given variable.
I assume you understand memory management in Objective-c ...
Accessors hide the complexity and differences of memory management for each variable.
For example:
name = #"Test"
is a simple assignment, name now holds reference to NSString #"Test". However you could decide to use copy or retain. No matter which version of memory management you chose accessor hides the complexity and you always access the variable with (or similar):
[self setName:#"Test"]
[self name]
Now setName: might use assign/copy or retain and you don't have to worry about it.
My guess is that iPhone tutorials use properties to make it easier for new developers to jump through memory management (even though it's handy to generate appropriate accessors with properties rather than implement them by hand every time).
However, in the iPhone world, things seem to be different. People declare properties for every single instance variable, declare properties for IBOutlets, and use accessors/mutators to interact with instance variables within the class (e.g. they would write [self setName:#"Test"] rather than name = #"Test").
That's not iPhone-specific. Except in init methods and the dealloc method, it's good practice to always use your accessors. The main benefit, especially on the Mac (with Cocoa Bindings), is that using your accessors means free KVO notifications.
The reason why people “declare properties for every single instance variable” is most probably that all of their instance variables are things they want to expose as properties. If they had something they would want to keep private, they would not declare a property for it in the header file. (However, they may make a property for it in a class extension in the implementation file, in order to get the aforementioned free KVO notifications.)
Declaring properties for outlets is overkill, in my opinion. I don't see a point to it. If you don't make a property, the nib loader will set the outlet by direct instance-variable access, which is just fine for that task.
I would suggest that modern development has made a very strong attempt to identify, define and apply best practices.
Among these best practices we find continuity and consistency.
Apart from arguing over use of accessors in init and dealloc methods, accessors should generally be used all the time (inside and outside of a class) for the benefits they offer, including encapsulation, polymorphic var implementations (which both allow for abstracting and refactoring) and to facilitate those best practices of continuity and consistency. The fundamental benefits of an object-orient language come into play when doing things in this way and exploiting the fullness of the language's capabilities. Always being consistent in one's coding is an oft undermentioned benefit, as any senior programmer will usually attest.
You can write like this
//MyClass.h
#class Something;
#interface MyClass : NSObject
#property (nonatomic, strong) NSString *name;
#property (nonatomic, strong) NSArray *items;
#end
//MyClass.m
#interface MyClass()
#property (nonatomic, strong) IBOutlet NSTextField *myTextField;
#property (nonatomic, strong) Something *something;
#end