How does the new Apple LLVM 4.0 "default synthesize" feature operate? - objective-c

I was going through the release notes for Xcode 4.4 and noticed this:
LLVM 4.0 Compiler
Xcode now includes the Apple LLVM Compiler version 4.0, including the following newObjective-C language features:
Default #synthesize: automatically synthesizes an #property when unimplemented
I'm intrigued about this feature. How does it work? I have tried by deleting the #synthesize, it doesn't work.

It does work actually, make sure that in your project and target settings the Compiler is set to LLVM 4.0. Then when you delete the #synthesize line you can access it in two ways:
through the accessor with self.myProperty or through the respective instance variable with _myProperty (yeah the underbars are added automatically).

There are many cases where it simply doesn't work. These are all outlined as exceptions here:
http://useyourloaf.com/blog/2012/08/01/property-synthesis-with-xcode-4-dot-4.html
but the most important one, to me, is called
Readwrite Property With Non-Default Getter and Setter
This means that, unless your properties are just public-facing ivars, you need to include a #synthesize. Or to put it another way, if you're using encapsulation well and filling up those setters and getters, you cannot use this.
Later Note: I'm not sure about the conditions specified here, but I find that there is a autosynthesized ivar for just about every situation I encounter.

Related

What is the fragile base class in Objective-C?

I'm reading a book of object-c. When talking about inheritence, the book says:
Methods use the self parameter to find the instance variables they
use.
The Objective-C compiler knows the layout of the instance variables in
an object because it has seen the #interface declarations for each of
these classes.
With this important knowledge, the compiler can generate code to find
any instance variable.
Then it says this can cause fragile base class problem:
The compiler works its magic by using a “base plus offset” mechanism.
Given the base address of an object—that is, the memory location of the first byte of the first instance variable—the compiler can find all other instance variables by adding an offset to that address.
When you access some instance variable in a method, the compiler generates code to take the value that self holds and add the value of the offset (4, in this case) to point to the location where the variable’s value is stored.
This does lead to problems over time.
These offsets are now hard-coded into the program generated by the compiler.
Even if Apple’s engineers wanted to add another instance variable to NSObject, they couldn’t, because that would change all of the instance variable offsets.
This is called the fragile base class problem.
Apple has fixed this problem with the new 64-bit Objective-C runtime introduced with Leopard, which uses indirection for determining ivar locations.
I don't understand why adding instance variable in NSObject can cause problem.
If NSOject changes, can't we just recompile the program so the offsets change accordinglly?
Edit: And what if we dont recompile, will the existing code just fail?
Yes, a recompile would fix things, but until you recompile, your program would be broken.
Imagine that you compile your app targeting 10.4. The compiler looks at the headers of NSObject and figures out what the appropriate offset is for each ivar in your subclass. Then 10.5 comes out and they add new ivars to NSObject. Anyone running your app on 10.5 will have problems, because the Foundation framework (which includes NSObject) was compiled against the 10.5 SDK, while your app is still relying on the layout that was present in the 10.4 SDK.
The fragile base class problem meant that Apple could not change the size of any framework class without crashing every app that did not recompile for the new SDK. While in an ideal world, developers would always release updates promptly, that's not reality. So until the fragile base class problem was fixed, Apple's hands were tied.
If Apple adds an ivar to NSObject, all of its subclasses would need to be recompiled, meaning a number very close to the 100% of all the Objective-C code ever written.
Do you see the problem now?
It's not impossible to solve, you just need to have every developer to recompile their code bases, but in the meanwhile every single Objective-C program out there would be broken.
As a further reference, here's a very nice article by Greg Parker on this subject: http://www.sealiesoftware.com/blog/archive/2009/01/27/objc_explain_Non-fragile_ivars.html

XCode 4.5 warns about method name conflicts between Categories for parent/child classes

I'm working on a project that was originally built in XCode 4.0, and then migrated to using XCode 4.2. Now I've tested out migrating to XCode 4.5, and I'm getting a ton of warnings like below...
instance method 'values' in category from <pathToTheFile>/HistoryObject+extras.o conflicts with same method from another category
These warnings never appeared in previous versions of XCode, and the code hasn't changed.
The project is set at iOS 4.3 for the Deployment Target.
So, we have from a previous developer a bunch of DAO type classes that I believe were auto-generated from CoreData, and then each of these classes has a Category that extends it to implement certain methods. I'll give an example...
We have a base class named LisaObject that inherits from NSManagedObject, and it has a Category named LisaObject+extras. In LisaObject+extras, there is a method named "values" that returns an NSMutableDictionary.
We then have a class named HistoryObject that inherits from LisaObject. There is also a Category for HistoryObject that is named HistroyObject+extras. This Category also has a method named "values". In the HistoryObject+extras values method, it calls [super values], and then checks for some conditions and sets some additional values in the dictionary that aren't set in the base class method.
We then have a class named LessonStatusObject that inherits from HistoryObject, and it too has a Category named LessonStatusObject+extras, which has a method named values. This values method also calls [super values] and then does some additional work on the returned dictionary.
For each of these "values" methods, we get a warning at compile time like the one shown above where it says the Category has a method with a conflicting name.
I have a few questions about this.
First, could this implementation cause any legitimate problems, or are these warnings generally benign? I've tried to think of how this implementation could cause an ambiguity at runtime, but I don't see how that could happen.
Second, is there something that I should do to fix these warnings (and I don't mean just make them stop appearing; I mean fix the cause)? Is there some other way we should be going about this?
Also, why would XCode 4.2 not warn about this, but XCode 4.5 does warn?
Am I misunderstanding something about Categories? I mean, if the "values" method was actually part of the each class implementation, it wouldn't be a problem to override them the way we do, but the compiler seems to be complaining simply because these are Categories. Is there anything unsafe about this?
Any advice is much appreciated.
EDIT: Just to provide more information... When we were using XCode 4.2, the project had the compiler set to Apple LLVM Compiler 3.0. Now when I open the project in XCode 4.5, it has the compiler set to Apple LLVM Compiler 4.1.
I had this same annoying issue and it turned out that I had accidentally included that category's .m file instead of the .h file in one of my VC's code. Correcting it to the .h file removed the linker warnings.
Do not ignore the warning.
Apple's "Programming With Objective-C" guide, in the "Customizing Existing Classes" section, says:
If the name of a method declared in a category is the same as a method
in the original class, or a method in another category on the same
class (or even a superclass), the behavior is undefined as to which
method implementation is used at runtime.
If it has been working for you, then it's luck.
I had this issue too, but was caused by something different again. For me it was that the category had been added to the Xcode project twice! I didn't discover that was the case until I went to rename one of the methods and saw in the refactoring preview that it listed the category file twice.

Xcode 4 automatically generates iVars when using #property,where can I find the official doc for this feature?

I have read "What's new in Xcode",but I can't find the official explanation for this feature.
Where can I find the official explanation? Which documentation? Thanks.
Assuming you mean that it auto-generates an ivar and getter and setter methods for you even if you omit the #synthesize: this is variously called default property synthesis, automatic property synthesis, and property autosynthesis.
There's not a lot of documentation. As far as I have found, there's no official documentation of how it works, just of the fact that it exists.
It's really a clang feature, not an Xcode feature. It appeared briefly in the version clang shipped with Xcode 4.0 DP 4, but was removed shortly after due to bugs. It reappeared in the version of clang shipped with Xcode 4.4. Here's the commit that added it, I think.
You can find it mentioned in the Objective-C Feature Availability Index.
It's also mentioned in the Clang Language Extensions.
From experimentation:
If you don't explicitly #synthesize a property and it generates an instance variable, it will automatically generate an ivar with the same type (and, under ARC, ownership qualification) as the declared property. The ivar name will be an underscore (_) followed by the declared property name.
If you don't explicitly #synthesize a readonly property, and you do include an explicit getter method, then clang will not automatically generate an ivar for you.
If you don't explicitly #synthesize a readwrite property, and you do include both an explicit getter and an explicit setter, then again clang will not automatically generate an ivar for you.
But I don't know of any official documentation of these behaviors.
You can find this in the Apple documentation in Objective-C Programming Language: Declared Properties under "Property Implementation Directives". Whether or not an ivar is synthesized automatically depends on what runtime you are using:
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.
iOS always uses the modern runtime so you never need to declare ivars explicitly.
This is part of the compiler, actually.
You can read that in the LLVM specification website.
I would also draw your attention to the Coding Guidelines for Cocoa which advises:
Avoid explicitly declaring public instance variables.
Developers should concern themselves with an object’s interface, not with the details of how it stores its data. You can avoid declaring instance variables explicitly by using declared properties and synthesizing the corresponding instance variable.

Recent Changes in Objective-C runtime/ Xcode 4.2 code

I've just started learning Obj-C and i'm a little confused. The videos I've been watching on Lynda.com were created with Xcode 4, but there are so many differences that I find it hard to believe that all of them occurred in 2 point releases. For instance:
In the video you could write:
#property NSString * myString
And it would be fine, but now in 4.2 it throws an error unless you write something like:
#property (nonatomic, retain) NSString * myString
In addition, there are no longer init or dealloc methods in the implementation code by default and NSAutoReleasePool is implemented completely differently. What gives?
While I can't guarantee that this list is exhaustive, the differences you'll find on the net are:
Objective-C 1.0 or 2.0
Old or modern runtime
Manual or automatic reference counting
My personal take on the main differences is:
Objective-C 2.0 brought properties and synthesized accessors among other things
The modern runtime has a different way of organizing instance variables (non-fragile instance variables), but you probably won't notice in day-to-day development work
The modern runtime also allows 64-bit apps if the OS supports it
Automatic reference counting lets you do away with retain/release code at the modest cost of following the coding and naming conventions
There are more differences, but these are the most important ones as I see it - personally I rarely have to use autorelease pools, and if I understand correctly the new syntax does not change the functionality.
If you create a project with "automatic reference counting" option "on" then there wouldn't be any init or dealoc methods.
When creating project
CHECK the Use Automatic Reference Counting.
When creating a project you can check the option "Use Automatic Reference Counting". If you do check this, then there won't be any init or dealloc methods, because Xcode automatically does the reference counting.

Objective-C properties, how do they work?

Assume we have a class Foo with a property bar.
Declared like this in the header:
#interface Foo : NSObject {
int bar;
}
#property (nonatomic, assign) int bar;
#end
In the .m I have #synthesize bar; of course.
Now, my question is, if I remove the int bar; line, the property behaves the same way, so, is that line really necessary? Am I missing some fundamental concept?
Thanks!
The "modern" Objective-C runtime generates ivars automatically if they don't already exist when it encounters#synthesize.
Advantages to skipping them:
Less duplication in your code. And the #property gives the type, name and use (a property!) of the ivar, so you're not losing anything.
Even without explicitly declaring the ivar, you can still access the ivar directly. (One old release of Xcode has a bug that prevents this, but you won't be using that version.)
There are a few caveats:
This is not supported with the "old" runtime, on 32-bit Mac OS X. (It is supported by recent versions of the iOS simulator.)
Xcode may not show autogenerated ivars in the debugger. (I believe this is a bug.)
Because of the debugger issue, at the moment I explicitly add all my ivars and flag them like this:
#interface Foo : NSObject {
#ifndef SYNTHESIZED_IVARS
int ivar;
#endif
}
#property (nonatomic, assign) int bar;
#end
My plan is to remove that block when I've confirmed the debugger is able to show the ivars. (For all I know, this has already happened.)
If there is not a instance variable (ivar) with the same name as the property the modern runtime creates a new ivar of the specified property name to hold the property value when it sees #synthesize.
If your property was not defined nonatomic and you want your code to be threadsafe it may help you to not reference the ivar (whether you declared it or it was synthesized), as that will prevent you from accessing it directly when the property is being changed. To my knowledge there is no way to acquire the same lock that is acquired by #synthesize for an atomic property and therefore you cannot perform safe reads of an atomic property's ivar other than by its synthesized accessor (unless you code an explicit setter and lock something yourself). If you are interested in writing you own accessors I have a blog post on that here.
I believe it is more usual to have an explicit ivar for each property, but this may be because most code is intended to be compatible with the legacy runtime rather than because it is inherently good practice.
Edit: I have corrected paragraph 1 to say that the synthesized ivar has the name of the property; I couldn't see any discussion of its name in Apple's docs so I had assumed it was not user accessible. Thanks to the commenters for pointing this out.
In the latest Objective-C runtime, it turns out that all ivars (in this case, bar) are dynamically added to the class from the #property/#synthesize declaration and do not need a corresponding ivar declaration in the class header. The only caveat to this is that latest Objective-C runtime which supports this feature does not include support for 32 bit applications.
This page from the excellent Cocoa with Love blog explains more.
If you are using the modern Obj-C runtime (e.g. with the LLVM compiler in Xcode 4), the compiler can automatically create the instance variable for you. In that case, you don't need to declare the ivar.
The modern runtime is supported by iOS, the iOS Simulator and 64-bit Mac OS X. You can't build your project for 32-bit OS X with the modern runtime.
I believe it only works that way in 64bit mode. If you try to build for a 32bit target, it will throw an exception.
Scott Stevenson has a good overview of the objective-c 2 changes, and mentions the 64bit runtime changes here