Under what conditions is #synthesize automatic in Objective-c? - objective-c

Under what conditions is #synthesize automatic in Objective-c?
Perhaps when using LLVM 3.0 and up? From reading around the net it seems like #synthesize is unnecessary starting with Xcode 4. However I'm using Xcode 4 and receiving warnings when I don't #synthesize a property.
Some of the responses to Why don't properties get automatically synthesized seem to imply #synthesize can be omitted at some point under some circumstances.
Another (old) reference hinting that #synthesize might be automatic at some point in the future.

As of clang 3.2 (circa February 2012), "default synthesis" (or "auto property synthesis") of Objective-C properties is provided by default. It's essentially as described in the blog post you originally read: http://www.mcubedsw.com/blog/index.php/site/comments/new_objective-c_features/ (except that that post describes the feature as "enabled, then disabled"; I don't know if that's an issue with Xcode or if the clang developers themselves have gone back and forth on the question).
As far as I know, the only case in which properties will not be default-synthesized in clang 3.2 is when those properties have been inherited from a protocol. Here's an example:
#import <Foundation/Foundation.h>
#protocol P
#property int finicky;
#end
#interface A : NSObject <P>
#property int easygoing;
#end
#implementation A
#end
int main() { A *a = [A new]; a.easygoing = 0; a.finicky = 1; }
If you compile this example, you'll get a warning:
test.m:11:17: warning: auto property synthesis will not synthesize property
declared in a protocol [-Wobjc-protocol-property-synthesis]
#implementation A
^
test.m:4:15: note: property declared here
#property int finicky;
^
1 warning generated.
and if you run it, you'll get an error from the runtime:
objc[45820]: A: Does not recognize selector forward:: (while forwarding setFinicky:)
Illegal instruction: 4

As of Xcode 4.4, if you don't write #synthesize or #dynamic for a property. the compiler acts as though you had written #synthesize property = _property.
Prior to Xcode 4.4, you must do one of the following things for each property or else the compiler will issue a warning and you will get a runtime error. In Xcode 4.4 or later, you may do any of the following things instead of letting the compiler automatically synthesize the property accessors and instance variable.
Use the #synthesize directive.
Use the #dynamic directive and somehow provide the property getter and (if necessary) setter at runtime.
Explicitly write the property getter method and, if the property is readwrite, the property setter method.
Note that you can use the #synthesize directive (or the #dynamic directive) and also explicitly provide the getter and/or setter methods. But #synthesize provides them if you omit them.

From the New Features in Xcode 4.4 document:
Objective-C #properties are synthesized by default when not explicitly implemented.
So #synthesize is automatic by default starting from Xcode 4.4 with the LLVM 4.0 Compiler.

Also, synthesize will not be automatic if you have implemented the setter AND getter manually. So if you wonder why you can't access _someVariable, having declared #property (...) SomeType someVariable, then it is because you have implemented the setSomeVariable: and someVariable methods.

You can turn off the synthesize warnings by clicking on the project name in the Project Navigator on the left then click All Cobined in Build Settings and then search for synthesize. That should be set to No.

Related

Is there a way to not #property then #synthesize?

I hate doing following
//in file.h
#property (strong) NSString *reuseIdentifier;
//in file.m
#synthesize reuseIdentifier = _reuseIdentifier;
This feels so redundant. I get the distinction of concepts between property in which is named "reuseIdentifier" and memory block that's named "_reuseIdentifier" but why can't the xcode IDE do the work by itself?
I feel like I am doing chores.
It's not been necessary to explicitly implement or synthesize Objective-C properties since Xcode 4.4 in 2012. See the Xcode 4.4 section of the archived "What's New in Xcode" documentation:
Objective-C #properties are synthesized by default when not explicitly implemented.

Why are there only sometimes compiler errors when accessing a property without self?

I noticed that in some old versions of Xcode you could use properties of objects without self just fine.
Now it gives me an error when I try to access my property without self, but today I'm writing this code, and it works fine, and doesn't give me any errors.
[aCoder encodeObject:itemName forKey:#"itemName"];
Why is it this way? Why don't I get an error in this case? Why is an error raised in other cases? Why can't this behavior be unified, and what should I use?
You have never been able to access properties without self. If you didn't use self, then you were directly accessing the instance variable that had the same name as the property. This has caused endless issues for many developers.
This is why the latest compilers (in the latest versions of Xcode) generate property ivars with a leading underscore. This way, if you forget to use self when trying to access the property, you get an error because there is no ivar with the same name.
To unify your experience you should use the following pattern with older compilers:
Define #property int foo;. Then define ivar int _foo. And then use #synthesize foo = _foo;.
With newer compilers you simply declare #property int foo and you are done. The compiler will generate the ivar int _foo for you.
In both cases you use self.foo for the property and _foo to directly access the ivar.
Whenever you create a property with new LLVM compiler, it creates an ivar named _property .
If you don't over-ride the auto-synthesized then you need to use _property or self.property.
In your case it looks like you are using old compiler (i.e. coming with XCode4.3 bacwards) or you have over-riden auto-synthesized as:
#synthesize aCoder;
I assume you mean this warning:
A lot of projects do not enable many warnings in their build settings, so that could be one reason that you aren't seeing this warning.
There are also certain methods where it is common to access instance variables directly, and Xcode will ignore direct ivar access; these include init* and dealloc methods (but unfortunately not getter/setter methods).
If you define properties in a class and #synthesize them to use the same naming, then you can access them without self
e.g.
In .h
#property(nonatomic, copy) NSString *str1;
In .m
#synthesize str1 = str1;
str1 = #"hello";
self.str1 = #"hello"; // Or this
If you don't use explicit #synthesize, then XCode automatically does #synthesize property = _property (since recently) so you can do the following
In .h
#property(nonatomic, copy) NSString *str1;
In .m
_str1 = #"hello";
self._str1 = #"hello"; // Or this
You won't be able to use self if the property is defined in a parent class. You'll have to synthesize in your current class to be able to use it.

objective-c properties - no attribute

I've just started reading through the Object-c developer handbook from apple. I'm playing with properties. I declared a class interface which has two properties:
#interface SocialEnglish : NSObject <IsSociable>
#property int numberOfPeopleMet;
#property (readonly) int readOnlyProperty;
#end
without declaring the instance variable associated to the properties. To my surprise, the compiler didn't complain. Then I wrote a bunch of code to access the instance object and sure enough the setters and getters worked as if I had implemented them and associated them to instance variables!
In the declaring class I can do something like this:
...
_readOnlyProperty = 3;
...
hmmm...I gota say as helpful as this maybe...I don't like it. Why doesn't the compiler complain and instead generates code. Is there a setting I need to set.
Also please note that I don't have a #synthesize directive in my implementation class.
Thanks!
The latest versions of Xcode automatically "synthesize" declared properties for you now. This came in with Xcode 4.0 (see the linked release notes under "Compiling: LLVM2.0").
If you want to call "#synthesize", or declare an "_readOnlyProperty" ivar or static and "#synthesize" to that, or write your own setters & getters, you can continue to do this.

Objective-C: Xcode automatically recognizes ' = _property ": is this #synthesize created variable name?

When you declare a #property and #synthesize it, it is considered good practice to use:
#synthesize myProperty = _myProperty;
I've noticed that Xcode will autocomplete the ivar name _myProperty for you, even though it hasn't yet been used in the source code.
Is this because the ivar #synthesize creates automatically defaults to the name _myProperty? Or merely because Xcode supports this common convention with an autocompletion for it?
Thanks.
EDIT: I'm not looking for reasons why this is good practice; I'm already aware of those and have used this convention for a while. I want to understand the internals, thus am asking whether this is a hard-coded auto-completion rule to satisfy a convention, or whether it's standard auto-completion and in fact the Objective-C specification dictates that an ivar generated by #synthesize must have the form _myProperty, thus after behind the scenes generation of the ivar, auto-completion is aware of its existence. Thanks!
I think the autocompletion is an IDE convenience rather than a result of the runtime. My logic for this is that the following appears to be valid:
#interface SomeClass()
#property (nonatomic, assign) int unpublishedInstanceVariable;
#end
#implementation SomeClass
#synthesize unpublishedInstanceVariable;
- (void)someMethod
{
unpublishedInstanceVariable = 3; // not calling the setter
}
#end
hard-coded auto-completion rule to satisfy the convention
If you don't specify an iVar name explicitly, it will be called myProperty. The autocomplete doesn't have anything to do with the compiler, it's just Xcode being extra helpful.
As of Xcode 4.4, there is a new twist to the tail (sic).
We are now allowed to skip the #synthesize altogether. In this case, the compiler automatically generates the #synthesize foo = _foo; declaration for us, with the instance variable name prefixed with an underscore.
#interface Foo : NSObject
#property (nonatomic, copy) NSString *foo;
#end
#implementation Foo
- (void)bar {
NSLog(#"%#", _foo); // this Works!
}
#end
However, if we do have an explicit #synthesize statement but do not specify the name of the instance variable, then the default name of the instance variable is the same as that of the property i.e. not prefixed with an underscore, in which case #Tommy's answer still holds.
It'd be great if someone could point out the links to official Apple Docs that document this behaviour.
Update
My findings were spot on. This behaviour (of #synthesize being the default, and creating a backing underscore prefixed instance variable in the absence of an explicit synthesize etc.) was publicly announced in WWDC 2012 Session 405 - Modern Objective-C.
wrt this part of your question:
whether ... in fact the Objective-C
specification dictates that an ivar generated by #synthesize must have
the form _myProperty,
You can name your ivar anything you want. From the docs:
You can use the form property=ivar to indicate that a particular
instance variable should be used for the property, for example:
#synthesize firstName, lastName, age=yearsOld;
This specifies that the accessor methods for firstName, lastName, and age should be
synthesized and that the property age is represented by the instance
variable yearsOld.
Also,
The #synthesize directive also synthesizes an appropriate instance variable if it is not otherwise declared.

Do declared properties require a corresponding instance variable?

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.