non ARC and weak property- ios 5 - iphone

I am using cocos2d v1.1.0-beta2b.
My project is NOT using ARC.
It used to work great but we have just tried changing now the minimal ios version for the project from 4.3 to 5.0 and we started to get compile time errors
"synthesize of weak properties is only allowed in ARC or GC mode"
it seems to be because of this(an example from cocos2d code)
// The delegate of the scroll layer object.
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_5_0
#property (nonatomic, weak) id<CCScrollLayerDelegate> delegate;
#else
#property (nonatomic, assign) id<CCScrollLayerDelegate> delegate;
#endif
What should i do to solve it?
Is it safe to simply remove this if from the code and leave just the line
#property (nonatomic, assign) id delegate; ?
(I am assuming it's ok as until today our code has used this anyway because until today we have targeted 4.3 and not 5)

__weak is an arc only feature and there is no official replacement
Try MAZeroingWeakRef by mike ash
(https://github.com/mikeash/MAZeroingWeakRef)
OR
PLWeakCompatibility by plausible labs
(https://github.com/plausiblelabs/PLWeakCompatibility)
--
You CAN fall back on assign and code will compile but as there is no automatic nilling of assign variables (as opposed To __weak vars) it changes semantics and may cause crashes down the road

Use unsafe_unretained instead of weak in your property declaration, and it should mostly work the same way.
unsafe_unretained is supported in both iOS 4.x and 5.0 and above, so it gives you backwards compatibility

Related

#synthesize IBOutlet property

I'm an Objective-C newbie and I'm reading "iPhone programming" by Alasdair Allan. While reading, I found this code:
#interface RootController : UIViewController <UITableViewDataSource, UITableViewDelegate> {
UITableView *tableView;
NSMutableArray *cities;
}
// warning: remember this tableView
#property (nonatomic, retain) IBOutlet UITableView *tableView;
The relative implementation starts this way:
#implementation RootController
#synthesize tableView;
Now: I learnt that #synthesize is a sort of shortcut to avoid boring getters and setters.
But I've some question:
in the code of the implementation tableView is never explicitly called but the dealloc releases it;
if it never gets called explicitly why the #synthesize?
Is it mandatory for IBOutlets to be synthesized?
From Memory Management of Nib Objects,
When a nib file is loaded and outlets established, the nib-loading mechanism always uses accessor methods if they are present (on both Mac OS X and iOS). Therefore, whichever platform you develop for, you should typically declare outlets using the Objective-C declared properties feature.
For iOS, you should use:
#property (nonatomic, retain) IBOutlet UIUserInterfaceElementClass *anOutlet;
You should then either synthesize the corresponding accessor methods, or implement them according to the declaration, and (in iOS) release the corresponding variable in dealloc.
in the code of the implementation tableView is never explicitly called but the dealloc releases it;
That is because when you do assign a value to the tableView, your controller retains it, and it will need to release it when it gets dealloc'd. Don't forget, #properties declared in an interface are publicly accessible. In your case specifically, the tableView you're declaring as IBOutlet is initialized by the view controller loadView method using the connections you define in Interface Builder between the File's Owner and the UITableView.
if it never gets called explicitly why the #synthesize?
You need to provide accessors for all declared #properties. They can be #synthesized, or you could write your own.
Is it mandatory for IBOutlets to be synthesized?
No, but it's way more convenient that way. The rule enforced by the compiler is that #properties must have corresponding accessors (synthesized or not) in the implementation.
For reference: From Xcode 4.4 and LLVM Compiler 4.0 on the #synthesize directive is no longer required as it will be provided by default for #properties defined in the interface.
If you type
#property (nonatomic, retain) IBOutlet UITableView *tableView;
you tell the compiler: "Listen, there will be a getter and a setter. If appropriate, use them!" And it will use them when loading the nib.
Therefore you have to implement the getter and the setter otherwise the compiler will complain.
The IBoutlet pseudo-type is just a marker so that the InterfaceBuilder "knows" that the mentioned class-file has a handle/outlet to the UITableView instance.
When compiling IBOutlet is being removed by the preprocessor (InterfaceBuilder parses (looks at) the source files). It's similar with IBAction: it is being replaced with void by the preprocessor.
That said, you could use the reference to said instance to do stuff programmatically (Like adding/changing values of the UITableView)

UIWIndow Not Declared iOS 4.3 AppDelegate

I just downloaded the newest iOS SDK (4.3) and noticed that when I start a Window Based Application, the UIWindow is not declared in the header file, it is only mentioned as a property.
#import <UIKit/UIKit.h>
#interface GleekAppDelegate : NSObject <UIApplicationDelegate> {
IBOutlet UILabel *label;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#end
I would expect, and remember from older SDK's, that the above code should be
#import <UIKit/UIKit.h>
#interface GleekAppDelegate : NSObject <UIApplicationDelegate> {
IBOutlet UILabel *label;
UIWindow *window;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#end
Is that just a new feature of the SDK?
Thanks
The new Objective-C runtime has the ability to synthesize ivars without explicitly declaring them. From Runtime Difference in The Objective-C Programming Language:
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.
...
With the modern runtime, if you do not
provide an instance variable, the
compiler adds one for you.
From Runtime Versions and Platforms in Objective-C Runtime Programming Guide:
Phone applications and 64-bit programs on Mac OS X v10.5 and later
use the modern version of the runtime.
Other programs (32-bit programs on Mac OS X desktop) use the legacy
version of the runtime.
Also have a look at this questions:
Objective C: Why do we declare ivars in the .h member area if #property seems to do it automatically?
What is the underlying mechanism for ivar synthesis in the modern Objective C runtime
Automatic iVars with #synthesize

Xcode4 templates now use underscore on iVars?

I have noticed that with Xcode4 Apple has updated the application templates to include underscores before instance variables.
// Xcode4
#property (nonatomic, retain) IBOutlet UIWindow *window;
#synthesize window = _window;
.
// Xcode3
#property (nonatomic, retain) IBOutlet UIWindow *window;
#synthesize window;
I know there are differing opinions on the usefulness of this but I was just curious if the updated templates where:
(1) Highlighting a new best practice.
(2) Showing how Apple does things but meaning for you to do it the old way.
(3) Its just personal taste, it does not matter.
It's interesting because in the past (pre-iOS), Apple used to discourage the use of underscore prefixes for ivars:
Avoid the use of the underscore character as a prefix meaning private, especially in methods. Apple reserves the use of this convention. Use by third parties could result in name-space collisions; they might unwittingly override an existing private method with one of their own, with disastrous consequences. See “Private Methods” for suggestions on conventions to follow for private API.
But with a modern Objective-C runtime, I believe ivar naming conflicts in subclasses has been eliminated, so this is not a problem anymore. So I think that's why they're making the templates use an underscore prefix by default, to match what Apple's internal code looks like.

Header file declaration in iPhone

What is the difference between them:-
Approach 1:-
#interface EffortView : UIView {
}
#property (nonatomic, retain) UIView *homeView;
#end
Approach 2:-
#interface EffortView : UIView {
UIView *homeView;
}
#property (nonatomic, retain) UIView *homeView;
#end
I have synthesized the properties in both cases. Both of them works. I am using Xcode 4.0 on Mac 10.6.6
Please enlighten me.
Thank you All.
The first approach won't work on 32-bit Mac OS X runtimes because each property must have a corresponding instance variable. 64-bit and iOS runtimes automatically create the instance variable for you, so in that case, it is enough to use the second approach.
The bottom line is: if you are 100% sure that you won't ever target 32-bit Mac OS X systems and none of the components of your software will ever be used on that platform, you can safely omit the instance variables.

Is this undefined behaviour with Objective-C properties?

I had something like the following code in a project I recently worked on.
#interface DetailsViewController : UIViewContoller {
UIView* headerView_;
}
#property (nonatomic, retain) UIView* headerView;
#end
#implementation DetailsViewController
#synthesize headerView = undefinedVariableName_;
// ...
#end
undefinedVariableName_ was not defined anywhere in the project and was actually a much less obvious typo.
This compiled perfectly fine (no errors or warnings) and even ran fine on iOS 4. I did not catch this error until the program crashed on 3.1.3 firmware.
Does anyone know if the above behaviour is considered undefined? Is there a way to have the compiler catch such mistakes?
In the modern Objective-C runtime you don’t have to declare the ivars yourself, the compiler will create them for you at the point of #synthesize. If it crashed on the older iOS this version probably doesn’t support the modern runtime yet.