I create a new project using xcode4.2, and view the AppDelegate:
#property (strong, nonatomic) UIWindow *window;
I know the strong is a new qualify in Xcode for ARC.However I didn't select using ARC while creating the project. As a result it is boring me.
Moreover,what does the below mean:
#synthesize window = _window;
Is _window a instance variable? But it didn't declare in the header file.I can understand if _window declared in the header but failed in this style.
Is it kind of modern obj-c runtime?
thanks!
strong is effectively the same as retain. I'm not sure if the compiler automatically translates that into retain for non ARC code or not. If not, it should generate a warning I would think.
#synthesize window = _window;
says the backing instance variable for the property window is _window. In the modern run time for iOS and 64 bit OS X, the instance variable is created automatically if you don't explicitly declare it in your header.
Related
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.
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.
I saw this code snippet on the Internet (http://iphonedevelopment.blogspot.com/2008/12/outlets-property-vs-instance-variable.html):
#import <UIKit/UIKit.h>
#interface MyViewController : UIViewController {
UILabel *myLabel;
}
#property (nonatomic, retain) IBOutlet UILabel *myLabel;
#end
My question is...When #synthesize is called isn't the UILabel instance variable created automatically? What is the point of creating the instance variable in the header file.. Can you get away with just the #property?
When #synthesize is called isn't the UILabel instance variable created automatically?
Yes.
What is the point of creating the instance variable in the header file.
Personal preference. Some developers (like me) prefer to see a complete picture of the state of a class. It helps to see what instance variables are available, as well as check that all instance variables are released correctly.
It's also a relatively new feature. Older code wouldn't expect automatically-generated instance variables.
Can you get away with just the #property?
No, you need to #synthesize to get an automatically generated instance variables A property value that's generated programmatically would not map directly to any instance variable.
#synthesize will create the instance variable but you will not be able to see it in the debugger which can be downright inconvenient.
Consider filing a bug with Apple about this.
Yes you can get away with just the #property in Objective-c 2.0.
see: Do declared properties require a corresponding instance variable?
There are two different methods to declare IBOutlet.
In #interface section as variable:
IBOutlet UIButton *exampleButton;
Below the curve bracket but before #end of .h file as property:
#property (nonatomic, retain) IBOutlet UIButton *exampleButton;
What is the difference between these two methods and where should I use each one? Which method is better and in what cases?
Either one works fine in my experience. What doesn't work is declaring both the instance variable and the property "IBOutlet" -- that seems to really confuse things. If for some reason you want to avoid providing public access to your outlet, you can declare it as an instance variable and simply not create the property. On the other hand, now that the runtime will synthesize instance variables for you, many people are declaring only properties and skipping the explicit instance variable declaration; in that case, you'd obviously declare the property as the IBOutlet.
The #property combined with #synthesize setup the getter and setter methods for your objects. You should define it at least in the interface, and if you decide to create a property from it then you must also synthesize it the .m file.
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.