I know that the #property generates the getters and setters in Objective-c. But I've seen some classes where they declare attributes with their respective #property and some times just the #property with no attributes and seams to work the same way. Whats the difference?
I know that the #property generates the getters and setters in Objective-c.
No you don't. #property declares a property which is a getter and optionally a setter (for read/write properties). The generation of the getter and setter is done by the #synthesize in the implementation (or by you writing the getter and setter).
But I've seen some classes where they declare attributes with their respective #property
Do you mean like this?
#interface Foo : NSObject
{
Bar* anAttribute; // <<=== this is an instance variable
}
#property (retain) Bar* anAttribute;
#end
In the modern Objective-C run time, if you #synthesize the property, you can leave out the instance variable declaration and the compiler will put it in for you. Whether you explicitly declare the instance variable or not is a matter of personal preference.
Just to confuse you a bit, in the very latest compiler, you can omit the #synthesize and the compiler will put it in for you as long as you haven't explicitly created a getter or setter.
Under ios 5.0, there are ten different attributes you can attach to a property declaration: nonatomic, readwrite, readonly, getter=name, setter=name, strong, retain, copy, weak, assign. (strong, weak are new under ios 5.0 and are only meaningful if you use ARC).
nonatomic declares that variable access should not be protected against multithreaded concurrent access. This isn't the default, although 99% of the time it's what you want (since this protection makes your code run slower with no benefit if you're not doing multithreading).
readwrite/readonly should be fairly obvious - readwrite is the default, and if you declare a property readonly, it has no setter.
getter=, setter= control what the getter & setter methods should be called. If you omit them, they'll be called property name and set*property name*, respectively.
The remaining attributes (strong, weak, retain, copy, assign) are hints to the memory manager, and their behavior varies depending on whether you're using ARC or not. If you're not, then the "retain" property tells the setter method to automatically call retain on any object that it gets a reference to. This means that you must also call release in the deallocator.
The "assign" property tells the setter not to call retain - so if the object is released by another object, this pointer could be left dangling.
The "copy" property tells the setter to call retain and also to make a copy of the property - this is useful when you get, say, an NSDictionary and you don't want the caller to pass an instance of NSMutableDictionary and change the contents out from underneath you.
If you're using ARC, you'll normally only set "strong" or "weak". (strong is a synonym for retain, so they can be used interchangeably). "strong" tells ARC to retain the variable for you - "weak" tells it not to. "weak" is useful when you have a potential "retain cycle" where object A refers to object B and object A - if they both retain each other, you have a memory leak, so you'll want to make one of them a weak reference.
Related
As someone that's new to Objective-C can someone give me an overview of the retain, assign, copy and any others I'm missing, that follow the #property directive? What are they doing and why would I want to use one over another?
Before you know about the attributes of #property, you should know what is the use of #property.
#property offers a way to define the information that a class is intended to encapsulate.
If you declare an object/variable using #property, then that object/variable will be accessible to other classes importing its class.
If you declare an object using #property in the header file, then you have to synthesize it using #synthesize in the implementation file. This makes the object KVC compliant. By default, compiler will synthesize accessor methods for this object.
accessor methods are : setter and getter.
Example:
.h
#interface XYZClass : NSObject
#property (nonatomic, retain) NSString *name;
#end
.m
#implementation XYZClass
#synthesize name;
#end
Now the compiler will synthesize accessor methods for name.
XYZClass *obj=[[XYZClass alloc]init];
NSString *name1=[obj name]; // get 'name'
[obj setName:#"liza"]; // first letter of 'name' becomes capital in setter method
List of attributes of #property
atomic, nonatomic, retain, copy, readonly, readwrite, assign, strong, getter=method, setter=method, unsafe_unretained
atomic is the default behavior. If an object is declared as atomic then it becomes thread-safe. Thread-safe means, at a time only one thread of a particular instance of that class can have the control over that object.
If the thread is performing getter method then other thread cannot perform setter method on that object. It is slow.
#property NSString *name; //by default atomic`
#property (atomic)NSString *name; // explicitly declared atomic`
nonatomic is not thread-safe. You can use the nonatomic property attribute to specify that synthesized accessors simply set or return a value directly, with no guarantees about what happens if that same value is accessed simultaneously from different threads.
For this reason, it’s faster to access a nonatomic property than an atomic one.
#property (nonatomic)NSString *name;
retain is required when the attribute is a pointer to an object.
The setter method will increase retain count of the object, so that it will occupy memory in autorelease pool.
#property (retain)NSString *name;
copy If you use copy, you can't use retain. Using copy instance of the class will contain its own copy.
Even if a mutable string is set and subsequently changed, the instance captures whatever value it has at the time it is set. No setter and getter methods will be synthesized.
#property (copy) NSString *name;
now,
NSMutableString *nameString = [NSMutableString stringWithString:#"Liza"];
xyzObj.name = nameString;
[nameString appendString:#"Pizza"];
name will remain unaffected.
readonly If you don't want to allow the property to be changed via setter method, you can declare the property readonly.
Compiler will generate a getter, but not a setter.
#property (readonly) NSString *name;
readwrite is the default behavior. You don't need to specify readwrite attribute explicitly.
It is opposite of readonly.
#property (readwrite) NSString *name;
assign will generate a setter which assigns the value to the instance variable directly, rather than copying or retaining it. This is best for primitive types like NSInteger and CGFloat, or objects you don't directly own, such as delegates.
Keep in mind retain and assign are basically interchangeable when garbage collection is enabled.
#property (assign) NSInteger year;
strong is a replacement for retain.
It comes with ARC.
#property (nonatomic, strong) AVPlayer *player;
getter=method If you want to use a different name for a getter method, it’s possible to specify a custom name by adding attributes to the property.
In the case of Boolean properties (properties that have a YES or NO value), it’s customary for the getter method to start with the word “is”
#property (getter=isFinished) BOOL finished;
setter=method If you want to use a different name for a setter method, it’s possible to specify a custom name by adding attributes to the property.
The method should end with a colon.
#property(setter = boolBool:) BOOL finished;
unsafe_unretained There are a few classes in Cocoa and Cocoa Touch that don’t yet support weak references, which means you can’t declare a weak property or weak local variable to keep track of them. These classes include NSTextView, NSFont and NSColorSpace,etc. If you need to use a weak reference to one of these classes, you must use an unsafe reference.
An unsafe reference is similar to a weak reference in that it doesn’t keep its related object alive, but it won’t be set to nil if the destination object is deallocated.
#property (unsafe_unretained) NSObject *unsafeProperty;
If you need to specify multiple attributes, simply include them as a comma-separated list, like this:
#property (readonly, getter=isFinished) BOOL finished;
The article linked to by MrMage is no longer working. So, here is what I've learned in my (very) short time coding in Objective-C:
nonatomic vs. atomic
- "atomic" is the default. Always use "nonatomic". I don't know why, but the book I read said there is "rarely a reason" to use "atomic". (BTW: The book I read is the BNR "iOS Programming" book.)
readwrite vs. readonly
- "readwrite" is the default. When you #synthesize, both a getter and a setter will be created for you. If you use "readonly", no setter will be created. Use it for a value you don't want to ever change after the instantiation of the object.
retain vs. copy vs. assign
"assign" is the default. In the setter that is created by #synthesize, the value will simply be assigned to the attribute. My understanding is that "assign" should be used for non-pointer attributes.
"retain" is needed when the attribute is a pointer to an object. The setter generated by #synthesize will retain (aka add a retain count) the object. You will need to release the object when you are finished with it.
"copy" is needed when the object is mutable. Use this if you need the value of the object as it is at this moment, and you don't want that value to reflect any changes made by other owners of the object. You will need to release the object when you are finished with it because you are retaining the copy.
After reading many articles I decided to put all the attributes information together:
atomic //default
nonatomic
strong=retain //default
weak= unsafe_unretained
retain
assign //default
unsafe_unretained
copy
readonly
readwrite //default
Below is a link to the detailed article where you can find these attributes.
Many thanks to all the people who give best answers here!!
Variable property attributes or Modifiers in iOS
Here is the Sample Description from Article
atomic
-Atomic means only one thread access the variable(static type).
-Atomic is thread safe.
-but it is slow in performance
-atomic is default behavior
-Atomic accessors in a non garbage collected environment (i.e. when using retain/release/autorelease) will use a lock to
ensure that another thread doesn't interfere with the correct setting/getting of the value.
-it is not actually a keyword.
Example :
#property (retain) NSString *name;
#synthesize name;
nonatomic
-Nonatomic means multiple thread access the variable(dynamic type).
-Nonatomic is thread unsafe.
-but it is fast in performance
-Nonatomic is NOT default behavior,we need to add nonatomic keyword in property attribute.
-it may result in unexpected behavior, when two different process (threads) access the same variable at the same time.
Example:
#property (nonatomic, retain) NSString *name;
#synthesize name;
Explain:
Suppose there is an atomic string property called "name", and if you call [self setName:#"A"] from thread A,
call [self setName:#"B"] from thread B, and call [self name] from thread C, then all operation on different thread will be performed serially which means if one thread is executing setter or getter, then other threads will wait. This makes property "name" read/write safe but if another thread D calls [name release] simultaneously then this operation might produce a crash because there is no setter/getter call involved here. Which means an object is read/write safe (ATOMIC) but not thread safe as another threads can simultaneously send any type of messages to the object. Developer should ensure thread safety for such objects.
If the property "name" was nonatomic, then all threads in above example - A,B, C and D will execute simultaneously producing any unpredictable result. In case of atomic, Either one of A, B or C will execute first but D can still execute in parallel.
strong (iOS4 = retain )
-it says "keep this in the heap until I don't point to it anymore"
-in other words " I'am the owner, you cannot dealloc this before aim fine with that same as retain"
-You use strong only if you need to retain the object.
-By default all instance variables and local variables are strong pointers.
-We generally use strong for UIViewControllers (UI item's parents)
-strong is used with ARC and it basically helps you , by not having to worry about the retain count of an object. ARC automatically releases it for you when you are done with it.Using the keyword strong means that you own the object.
Example:
#property (strong, nonatomic) ViewController *viewController;
#synthesize viewController;
weak (iOS4 = unsafe_unretained )
-it says "keep this as long as someone else points to it strongly"
-the same thing as assign, no retain or release
-A "weak" reference is a reference that you do not retain.
-We generally use weak for IBOutlets (UIViewController's Childs).This works because the child object only
needs to exist as long as the parent object does.
-a weak reference is a reference that does not protect the referenced object from collection by a garbage collector.
-Weak is essentially assign, a unretained property. Except the when the object is deallocated the weak pointer is automatically set to nil
Example :
#property (weak, nonatomic) IBOutlet UIButton *myButton;
#synthesize myButton;
Strong & Weak Explanation, Thanks to BJ Homer:
Imagine our object is a dog, and that the dog wants to run away (be deallocated).
Strong pointers are like a leash on the dog. As long as you have the leash attached to the dog, the dog will not run away. If five people attach their leash to one dog, (five strong pointers to one object), then the dog will not run away until all five leashes are detached.
Weak pointers, on the other hand, are like little kids pointing at the dog and saying "Look! A dog!" As long as the dog is still on the leash, the little kids can still see the dog, and they'll still point to it. As soon as all the leashes are detached, though, the dog runs away no matter how many little kids are pointing to it.
As soon as the last strong pointer (leash) no longer points to an object, the object will be deallocated, and all weak pointers will be zeroed out.
When we use weak?
The only time you would want to use weak, is if you wanted to avoid retain cycles
(e.g. the parent retains the child and the child retains the parent so neither is ever released).
retain = strong
-it is retained, old value is released and it is assigned
-retain specifies the new value should be sent -retain on assignment and the old value sent -release
-retain is the same as strong.
-apple says if you write retain it will auto converted/work like strong only.
-methods like "alloc" include an implicit "retain"
Example:
#property (nonatomic, retain) NSString *name;
#synthesize name;
assign
-assign is the default and simply performs a variable assignment
-assign is a property attribute that tells the compiler how to synthesize the property's setter implementation
-I would use assign for C primitive properties and weak for weak references to Objective-C objects.
Example:
#property (nonatomic, assign) NSString *address;
#synthesize address;
unsafe_unretained
-unsafe_unretained is an ownership qualifier that tells ARC how to insert retain/release calls
-unsafe_unretained is the ARC version of assign.
Example:
#property (nonatomic, unsafe_unretained) NSString *nickName;
#synthesize nickName;
copy
-copy is required when the object is mutable.
-copy specifies the new value should be sent -copy on assignment and the old value sent -release.
-copy is like retain returns an object which you must explicitly release (e.g., in dealloc) in non-garbage collected environments.
-if you use copy then you still need to release that in dealloc.
-Use this if you need the value of the object as it is at this moment, and you don't want that value to reflect any changes made by other
owners of the object. You will need to release the object when you are finished with it because you are retaining the copy.
Example:
#property (nonatomic, copy) NSArray *myArray;
#synthesize myArray;
Atomic property can be accessed by only one thread at a time. It is thread safe. Default is atomic .Please note that there is no keyword atomic
Nonatomic means multiple thread can access the item .It is thread unsafe
So one should be very careful while using atomic .As it affect the performance of your code
prefer this links about properties in objective-c in iOS...
https://techguy1996.blogspot.com/2020/02/properties-in-objective-c-ios.html
appDelegate.h
#property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
I had to do this in appDelegate.m
#synthesize managedObjectContext = _managedObjectContext;
I'm confused because according to apple
Note: The compiler will automatically synthesize an instance variable
in all situations where it’s also synthesizing at least one accessor
method. If you implement both a getter and a setter for a readwrite
property, or a getter for a readonly property, the compiler will
assume that you are taking control over the property implementation
and won’t synthesize an instance variable automatically. If you still
need an instance variable, you’ll need to request that one be
synthesized: #synthesize property = _property;
According to this it should create an instance variable as long as it created at least one accessor method. So does this mean that no accessors methods where created when I declared the property? What is the reason. Please explain.
I'm assuming somehow the compiler knows that NSManagedObjectContext has accessor methods. So it didn't create any and therefor it didn't create instance variables.
You haven't shown the code for the corresponding .m file, but I'm assuming you implemented the managedObjectContext property getter method programmatically. As the documentation says, "The compiler will automatically synthesize an instance variable in all situations where it’s also synthesizing at least one accessor method." But if you provide an implementation of the getter method for a readonly property, the compiler isn't synthesizing any accessor methods.
As the documentation says...If you provide atleast one accessor method for either setter or getter, its like telling the compiler...dont bother synthesizing this variable as I have some custom work to do with the setter/getter. Hence the compiler does not auto generate the _ivar. If you need the _ivar, you have to explicitly specify it and then proceed with your customer getter and setter. Its all about Objective C compiler doing things for you unless you say Don't bother...I know what I am doing.
I have readonly properties that I would like to declare similarly to other properties:
#property (nonatomic, readonly) MyThing *thing;
Frequently, I definitely do not want an instance variable and getter method to be automatically synthesised for these properties. In such cases I have made an error if I forget to write an explicit getter for them, and I want the compiler to tell me and refuse to compile (or at least, issue a warning).
In such cases, is it bad practice to use a #property declaration? Should I instead use:
-(MyThing*) myThing;
Or, alternatively, is there some way that I can tell #property in the attributes list (nonatomic, readonly, dont_synthesize_this_one_please) that I definitely don't want an instance variable to be sythesized and it's an error if I've missed out the getter?
No, there is no special attribute. If you don't overwrite the getter, the ivar will be synthesized.
Making the property a normal method as you suggest is the best solution.
You could also experiment with turning on the following compiler warning:
but then you will get warnings for ALL the synthesized properties.
You can also turn it on for every file separately -Wobjc-missing-property-synthesis
I'm a bit confused; if an object is declared in the .h file it is considered automatically as "public" right? We use a #property in the .h file, however, to edit them? This is where I don't understand: we use the getter/setter for private objects, so why do we use the #property for objects declared in the .h file and thus considered as "public"?
Second thing, I found this example: I don't understand why we use a #synthesize for primaryKey in this code: http://staging.icodeblog.com/wp-content/uploads/2008/08/9-todom1.png
and why we don't use a #property for the database object?
It is not correct that if an object (ivar) is declared in a .h file, then it is public. It is only if getter/setter methods are provided, otherwise it is not.
Indeed, the #property/#synthesize directives are facilities meant to declare and define default getter/setter methods. So, instead of writing them yourself, you just use the directives.
It is also worth noting that declaring properties you get the possibility of using the dot notation to refer properties of your objects. And also that they clarify a lot, thanks to the retain/assign/copy specifiers, how memory is meant to be managed for that properties. (And, of course, #synthesize will just do that correctly for you).
About your sample, in fact, whether an ivar is associated to a property or not is a design choice. Possibly, you just reconsider the assumption that ivars declared in .h files are public by defaults, and it will become clearer. In other words: primaryKey is public, database is not.
A very nice tutorial can be found here but also do not forget Apple docs.
EDIT:
about your question from the comment section:
it is not necessary that every ivar has a property, nor that it has getter/setter in order to be used inside of that class implementation.
#interface SomeClass : NSObject {
AnotherClass* _anotherClassObj;
AThirdClass* _aThirdClassObj;
}
#property (nonatomic, retain) AnotherClass* anotherClassObj;
#end
So, here you have two ivars; only one has got a #property declaration. In your .m file you may have, e.g.
#implementation SomeClass;
#synthesize anotherClassObj = _anotherClassObj;
- (void)initWithClasses:(AnotherClass*)obj1 and:(AThirdClass*)obj2 {
.....
self.anotherClassObj = obj1;
_aThirdClassObj = obj2;
...
}
....
#end
In this code:
#synthesize will provide implementation for getter/setter for anotherClassObj so you can use syntax: self.anotherClassObj = obj1; that syntax can be used equally from inside and outside the class implementation;
when you have no getter/setter (either auto-generated or custom) you can assign directly to an ivar by using the syntax _aThirdClassObj = obj2;, with the semantics of simple pointer copy; anyway, _aThirdClassObj will not accessible from outside that class;
furthermore, #property ... anotherClassObj notwithstanding, you can still refer _anotherClassObj directly in your .m file, like in _anotherClassObj = xxx, bypassing getter/setter, if you ever need it.
One thing you should have clear is that getter/setter are not only a way to make an ivar "public". They also play an important role in managing the retain count (depending on which specifier you choose among retain/assign/copy in the property declaration). So, in self.anotherClassObj = obj1; above, obj1 is assigned to _anotherClassObj and it is also retained (and if _anotherClassObj was previously pointing to an object, that object will be sent a release). Raw ivar assignment does not provide that kind of facility.
In my opinion, the retain count management feature of properties is far more important than visibility for deciding whether I use a property or not.
Not everything in the header is public, by default ivars (items in the { }) are #protected. The purpose of the #property is data encapsulation. #synthesize or #dynamic is used for declaring the way you want to implement your property and one or the other is necessary to prevent crashes and warnings.
Resources:
Defining Classes #protected, #package, #private, #public reference
Declared Properties #property reference
Do properties in Objective-C 2.0 require a corresponding instance variable to be declared? For example, I'm used to doing something like this:
MyObject.h
#interface MyObject : NSObject {
NSString *name;
}
#property (nonatomic, retain) NSString *name;
#end
MyObject.m
#implementation
#synthesize name;
#end
However, what if I did this instead:
MyObject.h
#interface MyObject : NSObject {
}
#property (nonatomic, retain) NSString *name;
#end
Is this still valid? And is it in any way different to my previous example?
If you are using the Modern Objective-C Runtime (that's either iOS 3.x or greater, or 64-bit Snow Leopard or greater) then you do not need to define ivars for your properties in cases like this.
When you #synthesize the property, the ivar will in effect be synthesized also for you. This gets around the "fragile-ivar" scenario. You can read more about it on Cocoa with Love
In your interface, you can formally declare an instance variable between the braces, or via #property outside the braces, or both. Either way, they become attributes of the class. The difference is that if you declare #property, then you can implement using #synthesize, which auto-codes your getter/setter for you. The auto-coder setter initializes integers and floats to zero, for example. IF you declare an instance variable, and DO NOT specify a corresponding #property, then you cannot use #synthesize and must write your own getter/setter.
You can always override the auto-coded getter/setter by specifying your own. This is commonly done with the managedObjectContext property which is lazily loaded. Thus, you declare your managedObjectContext as a property, but then also write a -(NSManagedObjectContext *)managedObjectContext method. Recall that a method, which has the same name as an instance variable/property is the "getter" method.
The #property declaration method also allows you other options, such as retain and readonly, which the instance variable declaration method does not. Basically, ivar is the old way, and #property extends it and makes it fancier/easier. You can refer to either using the self. prefix, or not, it doesn't matter as long as the name is unique to that class. Otherwise, if your superclass has the same name of a property as you, then you have to say either like self.name or super.name in order to specify which name you are talking about.
Thus, you will see fewer and fewer people declare ivars between the braces, and instead shift toward just specifying #property, and then doing #synthesize. You cannot do #synthesize in your implementation without a corresponding #property. The Synthesizer only knows what type of attribute it is from the #property specification. The synthesize statement also allows you to rename properties, so that you can refer to a property by one name (shorthand) inside your code, but outside in the .h file use the full name. However, with the really cool autocomplete that XCode now has, this is less of an advantage, but is still there.
Hope this helps clear up all the confusion and misinformation that is floating around out there.
it works both ways but if you don't declare them in the curly braces, you won't see their values in the debugger in xcode.
From the documentation:
In general the behavior of properties is identical on both modern and legacy runtimes (see “Runtime Versions and Platforms” in Objective-C Runtime Programming Guide). There is one key difference: the modern runtime supports instance variable synthesis whereas the legacy runtime does not.
For #synthesize to work in the legacy runtime, you must either provide an instance variable with the same name and compatible type of the property or specify another existing instance variable in the #synthesize statement. With the modern runtime, if you do not provide an instance variable, the compiler adds one for you.
If you are using XCode 4.4 or later it will generate instance variable synthesizing code for you.
You just have to declare properties like below; it will generate synthesizing code and instance variable declaring code for you.
#property (nonatomic, strong) NSString *name;
it will generate synthesizing code as
#synthesize name = _name;
and you can access instance variable using _name
it is similar to declare
NSString* _name
but if you declare read-only property it like
#property (nonatomic, strong, readonly) NSString *name;
it will generate code
#synthesize name;
or
#synthesize name = name;
So you should access instant variable name with out prefix "_"
any way you can write your own synthesizing code then compiler will generate code for you.
you can write
#synthesize name = _name;
The Objective-C Programming Language: Property Implementation Directives
There are differences in the behavior of accessor synthesis that depend on the runtime (see also “Runtime Difference”):
For the legacy runtimes, instance variables must already be declared in the #interface block of the current class. If an instance variable of the same name as the property exists, and if its type is compatible with the property’s type, it is used—otherwise, you get a compiler error.
For the modern runtimes (see “Runtime Versions and Platforms” in Objective-C Runtime Programming Guide), instance variables are synthesized as needed. If an instance variable of the same name already exists, it is used.