Can a property be declared with #synthesize only without #property? - objective-c

I found the following code in my project (using ARC). It looks like there is no property adDisplay declared. Only a synthesized statement and the compiler doesn't complain about it.
#interface MyClass() <MyProtocol> {
AdDisplay * _adDisplay;
}
#end
#implementation
#synthesize adDisplay = _adDisplay;
...
#end
Do I need to add
#property (nonatomic, strong) AdDisplay * adDisplay;
if I want to make sure adDisplay is strongly retained?
thanks
Update: it is declared in the protocol indeed. Does that count as instance variable?

A property in Objective-C is a name for a pair of methods: a setter and a getter. Declaring a property means saying that these two methods exist (for readwrite properties).
There does not have to be any real storage or memory management. Historically, under manual memory management, assign, retain, or copy would affect how the methods are synthesized.
However, under ARC, this is no longer needed. When you declare a property as strong or weak, it does not affect the body of the method, but only the type of the ivar.
Since you have an ivar declared manually
AdDisplay * _adDisplay;
(as strong)
then strong or weak inside the #property declaration won't have any real effect, only as a documentation for the API consumers.
The following would also work:
#interface MyClass() <MyProtocol>
#end
#implementation
#synthesize adDisplay;
#end
Also note this used to be a common memory leak problem when migrating projects from MRC to ARC. A property declared as weak, with an ivar declared as strong.

Related

#property vs just declaring getter and setter

Is there any difference in behaviour - either at compile time or at run time - between this code...
// MyClass.h
#interface MyClass : NSObject
#property (nonatomic) SomeType myProperty;
#end
// MyClass.m
#implementation MyClass
#end
... and this code?
// MyClass.h
#interface MyClass : NSObject
-(SomeType)myProperty;
-(void)setMyProperty:(SomeType)myProperty;
#end
// MyClass.m
#implementation MyClass {
SomeType _myProperty;
}
-(SomeType)myProperty {
return _myProperty;
}
-(void)setMyProperty:(SomeType)myProperty {
_myProperty = myProperty;
}
#end
Obviously, the former version is more succinct and readable, but is there any difference in behavior? Do the synthesized getter and setter do anything more sophisticated than my straightforward implementation here? Is the declaration of a property distinguishable by introspection functions from declaration of a getter and setter? Are there any other differences I haven't thought of?
Short answer: No difference. However, some property attributes (copy or atomic) may require different accessor methods.
Long answer: There is a group of introspection functions that allow you to access all #properties declared for given class or protocol:
class_getProperty
class_copyPropertyList
protocol_getProperty
protocol_copyPropertyList
property_getName
property_getAttributes
I don't think any of these functions is useful in production code, because this is basically an implementation detail of the class. Also, there may be a getter/setter exposed in the public interface and a private property hidden in class extension.
Oh, and there's one other difference: Xcode highlights properties and plain getters differently :)
One difference is memory management. You can configure your properties to for example copy the object being set or to use a weak variable. Your code seem to be assuming ARC is active, since you are not releasing the old object and retaining the new object.
Before ARC a typical setter would to something like
-(void)setMyProperty:(SomeType *)myProperty {
if (myProperty == _myProperty) return;
[_myProperty release];
_myProperty = myProperty;
[_myProperty retain];
}
When you say you use ARC, then there is only a small difference. But none that matters.
Your ivar is #protected.
A #property creates an ivar which is #private.
Generally speaking:
So when you subclass, it is possible for your subclass to directly access the ivar you created, but not the one the property created.
BUT since you put your ivar in the #implementation block, the ivar is never seen by the subclass.
Without ARC however and SomeType being not an Objective-C object, there is a big difference. Then your setter/getter wouldn't have retain/release messages included.

Quick inquiry about ivars scope [duplicate]

If you have a property in your public interface like the following
#interface MyClass : NSObject
#property(strong) NSString *myProp;
#end
And then synthesize it, in effect synthesizing the variable:
#implementation MyClass
#synthesize myProp = _myProp; // or just leave it at the default name..
#end
What is the visibility of the instance variable _myProp? That is, is this considered #public, #protected or #private? I'm guessing since MySubClass could inherit from MyClass then it would also get the properties (naturally), but would it also inherit the instance variable visibility?
What difference does it make if I put the property in a class extension? That would hide the property from subclasses, and I'm guessing the instance variable, too. Is this documented anywhere?
A synthesized ivar is completely invisible to all code that cannot see the #synthesize line (which basically means anything outside of the .m file). It's not #protected, it's not #private, it's simply unknown. With a #private ivar, other code trying to access it will be told that it's private, but with a synthesized ivar, other code trying to access it will be told that the field simply doesn't exist.
As a thought experiment, try imagining a situation where the ivar acted like it was #protected. You make a subclass, and you muck about with the ivar there. Now you go back to the superclass and change #synthesize myProp to #synthesize myProp=foo. What happens in the subclass? When the compiler processes the subclass, it cannot see the #synthesize line, so it would have no idea that you just changed the name of the ivar. In fact, it cannot even tell if the property is backed by an ivar at all, or if it's implemented with custom-written accessor methods. I hope it's obvious why this means that the subclass cannot possibly access the ivar, and neither can any other class.
That said, I'm not quite sure what the compiler does if you write code in the same .m file that tries to access the ivar. I expect it will treat the ivar as #private (since the compiler can, in fact, see that the ivar exists).
Also, none of this has any bearing on the runtime methods. Other classes can still use the obj-c runtime methods to dynamically look up your class's ivar list and muck about with it.
If it is declared in your interface it is virtually public when using the #property declarative. If you want to use #property declaratives and keep them property truly private, you should create a private category in your implementation.
MyClass.h
#interface MyClass : NSObject {
#private
NSObject* foo;
}
#end
MyClass.m
#import "ClassWithPrivateProperty.h"
#interface MyClass ()
#property (nonatomic,retain) NSObject* foo;
#end
#implementation MyClass
#synthesize foo;
// class implementation...
#end
A synthesized variable acts as if declared #private:
#interface Garble : NSObject
#property (copy) NSString * s;
#end
#implementation Garble
#synthesize s;
#end
#interface Bargle : Garble
#end
#implementation Bargle
- (void) useS {
NSLog(#"%#", s); // error: instance variable 's' is private
}
#end
I swear I've seen this in the docs, but I can't find it right now. Will update if I track it down.
You can create a dynamic property and indicate it to the compiler that its instantiation would be at run time.
And then in your subclass write your own getter or synthesize the property.
#interface BaseClass : NSObject
#property (nonatomic, strong) NSString *ThisWillBeSynthesizedInRespectiveSubclasses;
#end
#implementation BaseClass
#dynamic ThisWillBeSynthesizedInRespectiveSubclasses;
#end
In Sub classes
#interface Subclass : BaseClass
#end
#implementation Subclass
#synthesize ThisWillBeSynthesizedInRespectiveSubclasses = _ThisWillBeSynthesizedInRespectiveSubclasses;
#end
or you write your own setter / getter methods.
Hope this helps !
Other classes have access to everything that they #include. In other words, to everything that is inside your header.
If something appears only in your implementation file, other classes (including subclasses) don't know it exists. A synthesized property is like that. Other classes know only about the property (a property means a getter and a setter method) but they don't know anything about the inner implementation of its methods.
Note, that the access specifiers (public/private/protected) in obj-c are only a hint to the compiler that even if something appears in the header file, it can't be accessed. The runtime does not check it in any way.
What happens if you put it into a class extension? Note that a property is a set of two methods. You just hide the methods from every class which includes your class main header but not the class extension header.
We use this for example to declare a property as readonly and in class continuation we declare it as readwrite. Then, we can use the setter only from inside of the class.

What is the visibility of #synthesized instance variables?

If you have a property in your public interface like the following
#interface MyClass : NSObject
#property(strong) NSString *myProp;
#end
And then synthesize it, in effect synthesizing the variable:
#implementation MyClass
#synthesize myProp = _myProp; // or just leave it at the default name..
#end
What is the visibility of the instance variable _myProp? That is, is this considered #public, #protected or #private? I'm guessing since MySubClass could inherit from MyClass then it would also get the properties (naturally), but would it also inherit the instance variable visibility?
What difference does it make if I put the property in a class extension? That would hide the property from subclasses, and I'm guessing the instance variable, too. Is this documented anywhere?
A synthesized ivar is completely invisible to all code that cannot see the #synthesize line (which basically means anything outside of the .m file). It's not #protected, it's not #private, it's simply unknown. With a #private ivar, other code trying to access it will be told that it's private, but with a synthesized ivar, other code trying to access it will be told that the field simply doesn't exist.
As a thought experiment, try imagining a situation where the ivar acted like it was #protected. You make a subclass, and you muck about with the ivar there. Now you go back to the superclass and change #synthesize myProp to #synthesize myProp=foo. What happens in the subclass? When the compiler processes the subclass, it cannot see the #synthesize line, so it would have no idea that you just changed the name of the ivar. In fact, it cannot even tell if the property is backed by an ivar at all, or if it's implemented with custom-written accessor methods. I hope it's obvious why this means that the subclass cannot possibly access the ivar, and neither can any other class.
That said, I'm not quite sure what the compiler does if you write code in the same .m file that tries to access the ivar. I expect it will treat the ivar as #private (since the compiler can, in fact, see that the ivar exists).
Also, none of this has any bearing on the runtime methods. Other classes can still use the obj-c runtime methods to dynamically look up your class's ivar list and muck about with it.
If it is declared in your interface it is virtually public when using the #property declarative. If you want to use #property declaratives and keep them property truly private, you should create a private category in your implementation.
MyClass.h
#interface MyClass : NSObject {
#private
NSObject* foo;
}
#end
MyClass.m
#import "ClassWithPrivateProperty.h"
#interface MyClass ()
#property (nonatomic,retain) NSObject* foo;
#end
#implementation MyClass
#synthesize foo;
// class implementation...
#end
A synthesized variable acts as if declared #private:
#interface Garble : NSObject
#property (copy) NSString * s;
#end
#implementation Garble
#synthesize s;
#end
#interface Bargle : Garble
#end
#implementation Bargle
- (void) useS {
NSLog(#"%#", s); // error: instance variable 's' is private
}
#end
I swear I've seen this in the docs, but I can't find it right now. Will update if I track it down.
You can create a dynamic property and indicate it to the compiler that its instantiation would be at run time.
And then in your subclass write your own getter or synthesize the property.
#interface BaseClass : NSObject
#property (nonatomic, strong) NSString *ThisWillBeSynthesizedInRespectiveSubclasses;
#end
#implementation BaseClass
#dynamic ThisWillBeSynthesizedInRespectiveSubclasses;
#end
In Sub classes
#interface Subclass : BaseClass
#end
#implementation Subclass
#synthesize ThisWillBeSynthesizedInRespectiveSubclasses = _ThisWillBeSynthesizedInRespectiveSubclasses;
#end
or you write your own setter / getter methods.
Hope this helps !
Other classes have access to everything that they #include. In other words, to everything that is inside your header.
If something appears only in your implementation file, other classes (including subclasses) don't know it exists. A synthesized property is like that. Other classes know only about the property (a property means a getter and a setter method) but they don't know anything about the inner implementation of its methods.
Note, that the access specifiers (public/private/protected) in obj-c are only a hint to the compiler that even if something appears in the header file, it can't be accessed. The runtime does not check it in any way.
What happens if you put it into a class extension? Note that a property is a set of two methods. You just hide the methods from every class which includes your class main header but not the class extension header.
We use this for example to declare a property as readonly and in class continuation we declare it as readwrite. Then, we can use the setter only from inside of the class.

Do the ARC compiler automatically determines whether to retain or assign in overridden class depending on property attributes?

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.

Property syntax, Am I accessing the ivar directly or going through the getter/setter?

I am new to objective-c and am a little confused as to what I am accessing by when calling a property various ways in code.
// MyClass.h
#interface MyClass : NSObject {
}
#property ( nonatomic, retain ) NSString *name;
#end
//MyClass.m
#import "MyClass.h"
#implementation MyClass
#synthesize name;
// other code...
#end
I am unclear whether I am accessing the backing ivar or going through the getter and setter in using the following syntax (I will include my assumptions as to what I think it's doing):
name = #"Geoff"; is this going through the property setter or setting the ivar directly?
self.name = #"Geoff"; going through the setter
self->name = #"Geoff;" direct ivar access
[ name release ]; is this accessing the ivar directly or going through the getter?
I know this can be disambiguated by setting the ivar in the synthesize statement like: #synthesize name=_name as is done in a lot of the XCode 4 IOS templates.
name = #"Geoff"; is setting the ivar directly.
[ name release ]; is accessing the ivar directly.
If you don't see self. and you aren't calling a method to get or set the variable, then you are accessing the ivar.
For more details, see The Objective-C Programming Language.