I'm learning objective-c and there is something I couldn't find an answer to.
I have declared a property in the public interface of a class.
In that class I can access the ivar directly by using underscore, without synthesizing the property.
For example:
// Class.h
#property (nonatomic, strong) NSString *someString;
// Class.m
_someString = something;
But if I subclass that class, I can access the setter and getter without any extra code, but I can't access the ivar directly, unless I explicitly synthesize the property, which was not necessary step in the superclass.
I know for a fact that it does create ivars specific for the subclass, because I have 2 subclasses of the same superclass, and each have their own values for the superclass's properties.
I just don't understand why I need to explicitly synthesize the subclass if I want to access the ivars directly.
It isn't really a problem, but more of a curiosity.
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.
When defining a strong property in an interface, like so:
#property (nonatomic, strong) UIColor *petColor;
It is no longer required to add #synthesize, or #dynamic, or to manually define the internal ivar as _petColor, this all just works. The setters/getters are automatically generated, and you can access _petColor internally without any additional code.
However, I'm a little confused as to how (if at all), when overriding a setter, ARC knows whether to insert the retain/release calls depending on whether the property is strong or weak? For example, if I have two properties:
#property (nonatomic, strong) UIColor *petColor;
#property (nonatomic, weak) SomeClass *petDelegate;
If I want to override the setters for these properties, it seems they would be almost exactly the same?
- (void)setPetColor:(UIColor *)theColor {
if (![theColor isEqual:petColor]) {
_petColor = theColor;
}
}
- (void)setPetDelegate:(SomeClass *)theDel {
if (theDel != petDelegate) {
_petDelegate = theDel;
}
}
Is this correct? And if so, is ARC automatically inserting the proper retain/release calls in both of those setters, or only in the overridden setter for the strong property?
Further: Does the weak property behavior differ, in this situation, from the assign property behavior?
It's even simpler than that. When synthesizing, the instance variables get the respective qualifiers:
#implementation MyClass {
// this is what is added by the auto synthesize
UIColor * __strong _petColor;
SomeClass * __weak _petDelegate;
}
So when you assign to the instance variables using own setters, everything is fine, except for the copy qualifier. That one cannot be used for an instance variable, so then assign a copy to the instance variable.
Regarding assign (or the equivalent unsafe_unretained) for object properties, the instance variable would just be a pointer, and be synthesized to
SomeClass * __unsafe_unretained _petDelegate;
So if the object assigned to the property is deallocated, the pointer would not be set to nil as with weak, but point to where the deallocated object lived before. That may lead to crashes. As a rule of thumb, if you write your code for iOS 5 or later, always use weak instead of assign or unsafe_unretained on object properties.
Setting the strong, weak, or assign attributes of a property tells the compiler the storage class of the underlying data. If that is an auto-generated iVar, then it maps as following:
strong -> __strong
weak -> __weak
assign -> __unsafe_unretained
If you don't use an auto-generated iVar, then whatever data you have feeding the property is expected to conform to those storage class mappings.
See: Objective-C Automatic Reference Counting (ARC) : Property declarations
I'm following the guide here to create a custom delegate. It runs fine but I get the following warning in xcode
DetailViewController.m:23:1: Autosynthesized property 'delegate' will
use synthesized instance variable '_delegate', not existing instance
variable 'delegate'
Can anyone advise how to get rid of the warning
The most idiomatic way to handle this situation is simply to remove your delegate ivar declaration. If you were using your delegate ivar, you should use the implicit ivar _delegate instead.
Why does this work?
As of Xcode 4.4 (LLVM Compiler 4.0), instance variables and accessor methods are synthesized automatically for a property if the #synthesize directive is not used explicitly for that property. As Apple's documentation on encapsulation states
By default, [...] accessor methods are synthesized automatically for you by the compiler, so you don’t need to do anything other than declare the property using #property in the class interface.
The ivar that is used for a property (which is gotten and set by the automatically synthesized property accessor methods) is named _<propertyName> (i.e. the ivar's name is the property's name prefixed with an underscore).
In this case the property name is delegate, so the the ivar that is used is _delegate. This is already happening in your code. When you call -delegate and -setDelegate:, this ivar _delegate will be gotten and set.
However, you've also declared your own ivar delegate. Of course, the ivar you explicitly declared (delegate) will not be gotten and set by the instance methods -delegate and -setDelegate: since the automatically synthesized ivar (_delegate) is being gotten and set. However, (almost always--if it wasn't, your code is ambiguous) your intent was for your ivar delegate to be the thing that your property's accessors would get and set. Luckily, the compiler is clever enough to notice what you've done, and that's why it is emitting this warning:
warning: autosynthesized property 'delegate' will use synthesized instance variable '_delegate', not existing instance variable 'delegate' [-Wobjc-autosynthesis-property-ivar-name-match]
It's telling you that your property delegate will use the automatically synthesized ivar _delegate rather than the ivar that you explicitly declared, delegate.
So if you simply delete your delegate ivar, the compiler will stop emitting this warning. If you were using the delegate ivar directly (not through the property), start using _delegate instead.
A minor variation on this option is to explicitly declare the same ivar (_delegate) that the automatic synthesis of the delegate property is creating. You can do this by replacing
#interface TheClass : TheSuperclass
{
//...
id<TheDelegateProtocol> delegate
//...
}
#end
with
#interface TheClass : TheSuperclass
{
//...
id<TheDelegateProtocol> _delegate
//...
}
#end
This works because automatic synthesis of a property will always use an ivar whose name is the property's name prefixed with an underscore. If no such ivar exists, the ivar will be generated. If it does exist, it will be used.
If instead you would prefer that your property's accessors set and get your ivar delegate you can add an #synthesize directive to your class' #implementation to tell the compiler to do just this:
#implementation TheClass
//...
#synthesize delegate = delegate;
//...
#end
The line #synthesize delegate = delegate; tells the compiler to use the ivar delegate (the right hand of the assignment) in the accessors for the property delegate (the left hand side of the assignment).
You can also omit the right hand side of the #synthesize assignment and just write
#implementation TheClass
//...
#synthesize delegate;
//...
#end
This works because a property with a manual #synthesize which does not explicitly specify the ivar to be gotten and set by its accessors (such as #synthesize delegate;) will use an ivar with the same name as the property, NOT prefixed by an underscore. This has to do with backwards compatibility.
There's another method and this one worked for me:
#property (nonatomic, unsafe_unretained) id <MyDelegate> delegate;
You can then add this to the implementation without error:
#synthesize delegate;
Also: This is ARC compliant.
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.
It is my understanding that setting an ivar now retains the object being assigned to it, since setting variables defaults to the strong qualifier. Because ivars are in the scope of the object they are declared in and strong retains objects within the scope of the variable, this means the ivars value would never be released while the object containing the ivar is still alive.
Is this correct?
If so, am I right in thinking that there is, in terms of memory management, no difference between a retaining (strong) property and a simple ivar anymore?
If a variable:
Is declared in a class using ARC.
Is used solely for class implementation (not exposed as part of the class interface).
Does not require any KVO.
Does not require any custom getter/setter.
Then it is appropriate to declare it as an ivar without a corresponding #property/#synthesize, and to refer to it directly within the implementation. It is inline with Encapsulation to declare this ivar in the class implementation file.
// MyClass.h
#interface MyClass : ParentClass
#end
// MyClass.m
#implementation MyClass {
NSString *myString;
}
- (void)myMethod {
myString = #"I'm setting my ivar directly";
}
#end
This ivar will be treated as __strong by the ARC compiler.
It will be initialized to nil if it is an object, or 0 if it is a primitive.
You can't use KVO and do custom getter and setters with instance variables other than that they are very similar when using ARC.