I am creating a viewController programmatically (hopefully the right way) My problem is that I previously created the controller in IB and have code I want to call in awakeFromNib. As I currently have things viewDidLoad works fine but awakeFromNib does not. Is there anyway to get awakeFromNib to call or an alternative method that I can use in its place?
#class MyViewController;
#interface TEST_ControllerAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
MyViewController *viewController;
}
#property(nonatomic, retain) IBOutlet UIWindow *window;
#end
.
#implementation TEST_ControllerAppDelegate
#synthesize window;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
viewController = [[MyViewController alloc] init];
[window addSubview:[viewController view]];
[window makeKeyAndVisible];
return YES;
}
- (void)dealloc {
[viewController release];
[window release];
[super dealloc];
}
#end
EDIT_001:
I have pretty much come to the conclusion that using viewDidLoad is going to be my best option, particularly as I want to initialise IBOutlet instance variables.
In order to be called, the awakeFromNib method must be parameter-less (no sender):
- (void)awakeFromNib {
// Do whatever is needed...
}
Take care of the casing, as no error or warning will be logged if you mistype the method.
Related
Basically, I have two view controllers inside the MainWindow.xib that can be viewed by clicking the Bar Button in my Navigation Controller. I wanted those two view controllers to be separated from the MainWindow.xib with their own header, implementation and xib files and still make Navigation Controller inside of MainWindow.xib work in them.
To better understand it, please see the codes below:
Thanks a lot!
TestAppDelegate.h
#import <UIKit/UIKit.h>
#interface TestAppDelegate : NSObject <UIApplicationDelegate>
{
//Navigation Controller
IBOutlet UINavigationController *navigationController;
//View Controllers
UIViewController *viewController;
UIViewController *viewController2;
UIViewController *viewController3;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
//Navigation Controller
#property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
//View Controllers
#property (nonatomic, retain) IBOutlet UIViewController *viewController;
#property (nonatomic, retain) IBOutlet UIViewController *viewController2;
#property (nonatomic, retain) IBOutlet UIViewController *viewController3;
- (IBAction)next;
- (IBAction)next2;
#end
TestAppDelegate.m
#import "TestAppDelegate.h"
#implementation TestAppDelegate
#synthesize window = _window;
//Navigation Controller
#synthesize navigationController;
//View Controllers
#synthesize viewController;
#synthesize viewController2;
#synthesize viewController3;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
//Navigation Controller
[self.window addSubview:[navigationController view]];
[self.window makeKeyAndVisible];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
}
- (void)applicationWillTerminate:(UIApplication *)application
{
}
- (void)dealloc
{
[viewController release];
[viewController2 release];
[viewController3 release];
[navigationController release];
[_window release];
[super dealloc];
}
- (IBAction)next {
[navigationController pushViewController:viewController2 animated:YES];
}
- (IBAction)next2 {
[navigationController pushViewController:viewController3 animated:YES];
}
#end
Inside MainWindow.xib:
http://i52.tinypic.com/10xa45f.png
I normally don't touch MainWindow.xib. I suggest the following:
Create a MainController which will be your MainView that subclass UIViewController by going to File > New > New File. That will create a .h/.m and nib file for each ViewController. There add whatever UI you want for your app. For Example, add two buttons and wire those buttons to IBActions in your MainController. This should be declared and implemented in your MainController.{h/m}, respectively.
After that create another two ViewControllers, the same way.
The body of those IBActions should create an instance of the your ViewControllers and then push them.
It would look something like this:
YourViewController *yvc = [[YourViewController alloc] init];
[self.navigationController pushViewController:yvc animated:YES];
[yvc release];
Finally, you have to push the MainController in your AppDelegate and add your NavigationController to the view.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
MainViewController *mvc = [[MainViewController alloc] init];
UINavigationController *unvc = [[UINavigationController alloc] init];
[unvc pushViewController:mvc animated:NO];
[mvc release];
[self.window addSubview:unvc.view];
[self.window makeKeyAndVisible];
return YES;
}
Set the "class" property in Interface Builder (third tab in the inspector, "Custom Class") to the name of the custom class you're planning to use, and then put the name of the .xib file you want to load from in the "NIB Name" (fourth tab).
The code you're using to push the viewController is alright. Make sure to never accidentaly dealloc any of the two UIViewController.
Speaking of which, keep in mind that this approach is keeping the ViewControllers always in memory, even when not in use. Another approach is to completely remove the IBOutlets for the two ViewControllers, and do something like:
- (IBAction)next
{
MyCustomViewController *customViewController = [[MyCustomViewController alloc] initWithNibName:<#NibName or nil#> bundle:[NSBundle mainBundle]];
[navigationController pushViewController:customViewController animated:YES];
[customViewController release];
}
This creates the object when needed (If I remember right, the UI elements from the xib are cached somewhere, so that may be irrelevant[citation needed]). Just something to keep in mind, depending on the frequency of use of your two ViewControllers.
In App Delegate do I:
need to release my "window" and "navigationController"? and
where abouts should I release it out of (a) applicationDidReceiveMemoryWarning and (b) dealloc?
Code Listing
#interface weekendviewerAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
UINavigationController *navigationController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
#implementation weekendviewerAppDelegate
#synthesize window;
#synthesize navigationController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
RootViewController *rootViewController = (RootViewController *)[navigationController topViewController];
rootViewController.managedObjectContext = self.managedObjectContext;
self.window.rootViewController = self.navigationController;
// Configure and show the window
[window addSubview:[navigationController view]];
[window makeKeyAndVisible];
return YES;
}
.
.
As Bolt clock commented you need to add a dealloc method in appDelegate class.
- (void)dealloc {
[navigationController release];
[window release];
[super dealloc];
}
Well #greg if you ever release your window or navigationController in applicationDidReceiveMemoryWarning dont u think your application will crash when ur application receives memory warning.
As #Bolt and #ishu said you need to release it in dealloc methods only.
Also in applicationDidReceiveMemoryWarning method you can release those class variables which are not going to be used after some point of time, as releasing them may cause your app to crash.
So choose wisely what variables are not important that might cause your application to crash or stop your app from working properly.
Hello
I have problem with didFinishLaunching methods. I am really getting confused about what was the problem and that's why I pasted all my code. The problem was the application didn't launch, it crashed, and it show me this message in console:
**[Demo1AppDelegate setMapViewController:]: unrecognized selector sent to instance 0x5649a30
2011-05-25 14:17:58.724 Demo1[10630:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Demo1AppDelegate setMapViewController:]: unrecognized selector sent to instance 0x5649a30'**
I am using this code
In Demo1appDelegate.h file
#import <UIKit/UIKit.h>
#import "MapViewController.h"
#interface Demo1AppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
MapViewController *mapViewController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#end
And in
Demo1AppDelegate.m file
#import "Demo1AppDelegate.h"
#interface Demo1AppDelegate ()
#property (nonatomic, retain) MapViewController *mapViewController;
#end
#implementation Demo1AppDelegate
#synthesize window;
#pragma mark -
#pragma mark Application lifecycle
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
MapViewController *viewController = [[MapViewController alloc] init];
self.mapViewController = viewController;
[viewController release];
[window addSubview:self.mapViewController.view];
[window makeKeyAndVisible];
return YES;
}
- (void)dealloc {
[mapViewController release];
[window release];
[super dealloc];
}
#end
I think
self.mapViewController = viewController;
is the problem. You do not have #synthesize for mapViewController. So you cannot access through self
Or another option is to try this
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
mapViewController = [[MapViewController alloc] init];
[window addSubview:mapViewController.view];
[window makeKeyAndVisible];
return YES;
}
You need to implement UIApplication
change
#interface Demo1AppDelegate : NSObject
to
#interface Demo1AppDelegate : NSObject < UIApplicationDelegate>
This will solve your problem
the problem is in this line self.mapViewController = viewController;
you forgot #synthesize mapViewController;
Synthesize your map view controller.
You have to #synthesize mapViewController; in Demo1AppDelegate.m
You should also add [mapViewController release]; in the dealloc method of Demo1AppDelegate.m (with mapViewController being an instance variable).
Add delegate as follows ... This might be the issue :
#interface Demo1AppDelegate : NSObject <UIApplicationDelegate>
Try adding
#class MapViewController
before #implementation Demo1AppDelegate in Demo1AppDelegate.h
Hey! Where you add the subview
[window addSubview:self.mapViewController.view]; [window makeKeyAndVisible];
Try without "self"
[window addSubview:mapViewController.view]; [window makeKeyAndVisible];
Just a flying guess.
I have to xibs, and I want to load which one the user wants in the settings. I'm just working on actually loading them and how would this been done.
This is the function in the delegate which I think would be where this happens.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self.window addSubview:viewController.view];
[self.window makeKeyAndVisible];
return YES;
}
This is the delegate header file.
#import <UIKit/UIKit.h>
#class myAppViewController;
#interface myAppAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
myAppViewController *viewController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet myAppViewController *viewController;
#end
So lets say I have a xib created called modernTheme, how would I load that or the myAppViewController. If someone could do this in a generic if statement, that would be great.
This looks like your viewController is being created 'in Interface Builder'. Instead of that you could create the ViewControllers yourself and add them dynamically. Your application:didFinishLaunchingWithOptions: could look something like this:
UIViewController *viewController;
if (showModernTheme) { // from your configuration
viewController = [[YourViewControllerA alloc] initWith…];
} else {
viewController = [[YourViewControllerB alloc] initWith…];
}
// assuming YourViewControllerA + B are inheriting from UIViewController
[self.window addSubview:viewController.view];
[self.window makeKeyAndVisible];
Hope that helps
–f
I have this code working, however I don't quite understand how it is managing to set the data source for the UITableViewController? Would this have to be occurring via Interface Builder settings somehow?
That is if you see the line "tableData = [[NSMutableArray alloc] initWithObjects: etc", and the fact that I don't see where my "tableData" instance variable here is actually assigned to be the data for the UITableView....
#interface RootViewController : UITableViewController <NewItemControllerDelegate> {
NSMutableArray *tableData;
}
#end
#implementation RootViewController
- (void)viewDidLoad {
[super viewDidLoad];
tableData = [[NSMutableArray alloc] initWithObjects:#"My Standard View", #"A Different View", nil]; // <== HOW IS THIS MANAGING TO SET THE VIEW WITH THE DATA
}
and for reference
#interface myProjectAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
UINavigationController *navigationController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
#end
#implementation myProjectAppDelegate
#synthesize window;
#synthesize navigationController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
// Add the navigation controller's view to the window and display.
[self.window addSubview:navigationController.view];
[self.window makeKeyAndVisible];
return YES;
}
PS (edit) So what I can't quite understand is the linkage between my "NSMutableArray *tableData" variable I declared in the RootViewController header file, and the actual UITableViewController's datasource so to speak? Is there a default "tableData" in a UITableViewController perhaps that is what I'm really setting or something, so I'm not really allocating new NSMutableArray to my variable I created but another one? (hope this makes sense)>
By default, UITableViewController sets itself as the delegate and datasource of its table view. Since your class is a subclass of UITableViewController, it does the same. Of course, this assumes that you have implemented all the UITableViewDataSource methods to actually use the tableData array (which you aren't showing us here).