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.
Related
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
I am including a file like this:
#import "BannerPhoneContentController.h"
however, when I try to use it like this:
bannerContentController = [[BannerPhoneContentController alloc] init];
I get the error:
Use of undeclared identifier 'BannerPhoneContentController';
what could be causing the code to seemingly ignore my import?
this is the header for banner content controller.
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import "BannerContentController.h"
#interface BannerPhoneContentController : BannerContentController <UIScrollViewDelegate>
{
UIScrollView *scrollView;
UIPageControl *pageControl;
NSMutableArray *viewControllers;
// To be used when scrolls originate from the UIPageControl
BOOL pageControlUsed;
}
#property (nonatomic, retain) UIScrollView *scrollView;
#property (nonatomic, retain) UIPageControl *pageControl;
#property (nonatomic, retain) NSMutableArray *viewControllers;
- (IBAction)changePage:(id)sender;
#end
EDIT bannerContentController is of type BannerContentController NOT BannerPhoneContentController. The latter is a subtype of the former. It is definitely worth noting that this exact code works just fine in another app, so it's nothing to do with the code itself - just how it's being included apparently. I'm stumped.
EDIT ok found the problem - not sure how to fix it. I generated the preprocessed file and the header file it's included is in fact this:
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import "ContentController.h"
#interface PhoneContentController : ContentController <UIScrollViewDelegate>
{
UIScrollView *scrollView;
UIPageControl *pageControl;
NSMutableArray *viewControllers;
// To be used when scrolls originate from the UIPageControl
BOOL pageControlUsed;
}
#property (nonatomic, retain) UIScrollView *scrollView;
#property (nonatomic, retain) UIPageControl *pageControl;
#property (nonatomic, retain) NSMutableArray *viewControllers;
- (IBAction)changePage:(id)sender;
#end
note the difference - all the 'Banner's are missing. This is what the file used to look like. However, I've checked and the file that's in the project is the one I posted at the top. I tried cleaning the solution and building again. How can I fix this and why has it happened?
EDIT The file that I'm including all this in is part of a code library. I have now created a new project, imported the code library and included all of this in that library once again in exactly the same way. and it works. I have looked over the two projects and the code in question is identical. This must be a project setting?
It looks for me like recursive import. Say, BannerContentController.h imports BannerPhoneContentController.h, and BannerPhoneContentController.h imports BannerContentController.h.
If it is the case, then you should resolve recursive dependencies. E.g. using forward declaration.
does using #class BannerPhoneContentController in .h and #import "BannerPhoneContentController.h" in .m gives the same result ?
After a lot of messing around, and thanks to a comment from Yuras I generated the preprocessed code and realised the problem was that the OLD version of the code was being included.
More useful is WHY. It's just a bug in XCode that happens sometimes when incremental linking is turned on - basically this is where time is saved by only changing the parts of the pre-processed file when the corresponding bits of your code have been altered. Unfortunately, this does not alway work correctly.
The solution, annoyingly, was to delete the files, clean the build, delete the derived data (window / oraniser / projects / project name / delete derived data), restart xcode (possibly also restart your computer, or throw it out of the window and buy a new one) then re-import the files.
XCode can be a real pain...
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)
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
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.