What is the best way to pass an object between two views and how would I go about doing so?
If you are using two view controllers then making property will be best way for you.
in .h file
NSString *name;
#property (nonatomic, retain) NSString *name;
and in .m
#synthesize name;
for more how to use property look -
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html#//apple_ref/doc/uid/TP30001163-CH17-SW1
Use the properties declared in each controller.
I'm assuming you have two view controllers, ViewController1 and ViewController2. In both header files (.h), add an instance variable:
CustomObject *myObjectToPass;
and also
#property (nonatomic, retain) CustomObject *myObjectToPass;
If you are passing a BOOL, int or float, then do not retain it, for an NSString, use copy in place of retain, etc.
In the implementation file (.m), synthesize the variable:
#synthesize myObjectToPass;
Now you can get and set the object between viewControllers. The best way to do this depends on how they are related (e.g. in a navigationController or a tabBarContoller, etc). This should get you started, though.
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.
If I have a UIImageView in an .xib file called MainViewController (which, of course, is linked with the respective MainViewController interface (.h) and implementation (.m) files), how can I change the image of the UIImageView from an entirely separate class?
I want to process all of the image initialisation from a separate class (there are a lot of images), but can't seem to figure out how to do it outside of MainViewController.m.
Any tips? Thanks.
Declare these ImageView as #property and access them in other classes.
#property (nonatomic, retain) IBOutlet UIImageView *image1;
In the implementation class
#synthesize image1;
Now you can use setter and getter from other classes to access these objects to play around.
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)
Basically I want to be able to access the UIApplication delegate's window property all the way through my class, so I want to reference it with an iVar.
To this end I don't want to "own" it, just reference it.
So therefore should I just put a variable reference in the .h file?
#import <UIKit/UIKit.h>
#interface MessageView : UIView {
UILabel *messageLabel;
UIWindow *window;
}
#property (nonatomic, retain) UILabel *messageLabel;
#end
Or should I set the property there too?
I'm sceptical because the property would be nonatomic, retain, but I don't want to retain it, unless I actually do and I'm just being thick! :p
The purpose of having the window object is just to be able to add subviews to it, rather than the current view controller's view.
Thanks
Why not use
#property (nonatomic, assign) UIWindow *window
Then you are not retaining it.
Given the window should exist for the lifetime of your app there is no real need to retain it as it's already being retained by your app delegate.
Having a property in the first place in this scenario is nothing more than syntactic sugar
someclass.window = self.window; // Using a property
is much more succinct than
window = [UIApplication sharedApplication].window; // Using an iVar
Well you actually do want to retain the UIWindow. New projects by default retain it and there is nothing wrong with that. I see that MessageView is inheriting directly from UIView and that has a window property that is set once it is added to a window(or a subview of a window). Also look at willMoveToWindow: and didMoveToWindow. Now never think that you can not create a property just because you do not want to retain something because that is what the assign keyword is for.
#import <UIKit/UIKit.h>
#interface MessageView : UIView {
UILabel *messageLabel;
UIWindow *window;
}
#property (nonatomic, retain) UILabel *messageLabel;
#property (nonatomic, assign) UIWindow *window;
#end
Actually, no, you do not.
Whenever you use any of the UIWindow Make Key Window methods (as you probably is doing inside your AppDelegate), such as
– makeKeyAndVisible
– makeKeyWindow
The window becomes available from all your application just by using the UIApplication's keyWindow property.
[[UIApplication sharedApplication] keyWindow]
So, there is no need for a property or a retain in your AppDelegate or anywhere else, as it will be retained by your application class.
OBS: The property is commonly placed in your AppDelegate as the application template from XCode used the interface builder and an IBOutlet to instantiate the UIWindow. So, if your are creating your window by hand, there is no need for a property there.
i recently updated my IDE to XCode 4.0 and saw a strange change in the Utillity-Application boiler-plate-code:
First, the MainViewController.h-File:
#import <UIKit/UIKit.h>
#class MainViewController;
#interface UtilityAppDelegate : NSObject <UIApplicationDelegate> {
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet MainViewController *mainViewController;
#end
Question 1: Where is "mainViewController" declared in the first place? I didn't find it anywhere.
In the *.m-File there is a
#synthesize mainViewController=_mainViewController;
statement. So my second question: Where is "_mainViewController" hidden? Can't find a declaration anywhere. It comes somehow out of the main *.nib file I guess.
But there is another problem: I did add a UINavigationController to one of my recent projects and have no need for mainViewController anymore. But when I delete #property and #synthesize out of MainViewController.m/.h , I can't run the app anymore because of this exception:
setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key mainViewController.'
occurring at this line
int retVal = UIApplicationMain(argc, argv, nil, nil);
in the main.m.
Thx for your help.
Look at you info.plist it's should be declared there. If you created your app with a template it's configured by the plist. There is some implicit declaration done by this, the mainWindow.xib(in my example) contains more than a window. There are the connections to the appDelegate and the viewController, see second screenshot.
The last line of the screenshot:
Question 1:
When you use a declaration like this, you don't also need to explicitly define the property.
.h
#property (nonatomic, retain) IBOutlet MainViewController *mainViewController;
.m
#synthesize mainViewController=_mainViewController;
Question 2:
_mainViewController is not hidden. It points to mainViewController which is implicitly defined in the #property statement in .h
#synthesize mainViewController=_mainViewController;
This format is used to distinguish between the ivar and other properties. It refers to mainViewController.
Question 3:
You deleted the declarations #property/#synthesize for mainViewController, but it still exists in the nib file (IB). Delete it from IB and you should be good to go.
You're encountering the new ABI for the first time. It is no longer necessary to actually declare variables for properties. If you use #property and #synthesize, a backing ivar will automatically be generated for you.
You're probably getting the KVC error because the NIB still references the old property. You should see a warning about this during compile. In IB, look at your App Delegate; it probably still has an outlet for mainViewController, and you probably are still generating a MainViewController. You need to delete them from the NIB.