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
Related
i have 15 to 20 Variable i wants access it in my whole project. what is the best place for defining it and why?.. Appdelegate File, .Pch file or define these Extern.
really thanks in Advance.
Accessing your app delegate from various points of your app creates a strong coupling between these components of your app.
Basically you are using globals through your app which is usually a good indication for an improvable application design.
Variables usually do not live in thin air. They exist in a context. For example if you are using username and password you should get them from the system's keychain. The whole authentification process should be wrapped in an authentification class in which you would define the properties.
If you need to access information from various places of your app, you have to pass them as arguments of the initializer for example. This btw renders your individual components testable which is a good thing.
My advice is to rethink your app design first to not end in dependency hell later on.
You can define them as properties in your AppDelegate class. For example:
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (retain, nonatomic) NSString *publicString;
If you want to make them readonly for external objects then you can define as follows:
1) in AppDelegate.h
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (retain, readonly, nonatomic) NSString *publicString;
2) in AppDelegate.m
#interface AppDelegate ()
#property (retain, readwrite, nonatomic) NSString *publicString;
#end
#implementation AppDelegate
#synthesize publicString;
// other methods below
#end
Create one header file by name 'defines.h' and implement all defines and constants in it.
import this file in .Pch file
This is the best one, and will be separate from other classes.
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 have a problem about making Mobile Substrate tweaks for iOS 5.
Most tutorial about making Cydia tweaks have this step: "Download private framework headers".
So, I downloaded it from : https://github.com/kennytm/iphone-private-frameworks
Since the private-frameworks are dumped from iOS 3.x, some new methods and variables are not included.
Therefore, I added these variables to my Tweak.xm. And I imported the private-framework-headers too.
For example:
#import "/opt/theos/include/UIKit/UIKit2.h"
#import "/opt/theos/include/UIKit/UIKeyboardLayoutStar.h"
#interface UIKeyboardImpl : UIView
#property(assign, nonatomic) BOOL showsCandidateInline;
#property(assign, nonatomic) BOOL showsCandidateBar;
#end
However, when I compile the tweak, I got these errors:
Tweak.xm:45: error: duplicate interface declaration for class ‘UIKeyboardImpl’
Tweak.xm:45: error: redefinition of ‘struct UIKeyboardImpl’
Tweak.xm:45: error: trying to finish struct, but kicked out due to previous parse errors
How can I do to fix this problem ?
Should I edit the private framework headers of iOS 3 and add new variables from iOS 5?
Thanks a lot
Adding a category will fix it.
#interface UIKeyboardImpl (YourCategory)
#property(assign, nonatomic) BOOL showsCandidateInline;
#property(assign, nonatomic) BOOL showsCandidateBar;
#end
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)
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.