I am trying to follow the apple photopicker example which has an appdelegate object in an .xib file. How does an appdelegate object get into a xib file, and why is it important?
In my app I want a navigation controller like the photopicker example has. My test work has not included a navigation controller and I am having difficulty inserting one into my test work now that it has just a view controller because the interface builder seems to have made up its mind to not allow the addition. Will it be easiest for me to just start over with a new app that has the navigation controller architecture and then add in copies of my test work methods and classes. Or is starting over unnecessary? I suspect that inserting the appdelegate object into the xib would allow me to use the exist test work more directly.
update 0
I think I followed the instructions in your answer. Xcode suggested _viewController and I changed that. My app is for both iPad and iPhone (and I am working only on iPad now), so it is a little more complicated, I think. I compile fine, but I still see no appdelegate object in my xib file even though PhotoPicker's xib file has one.
I suspect I need to hook up some objects still, but I could use some help with that, too. In PhotoPicker the Connections Inspector for the Navigation Controller says that the Referencing Outlet is between navController and AppDelegate, and the Connections Inspector for the AppDelegate says that the Referencing Outlet is between delegate and File's Owner. But because my xib file has no (BS)AppDelegate object, I don't know how to hook up without it.
#interface BSAppDelegate ()
#property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
#end
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
self.viewController = [[BSViewController alloc] initWithNibName:#"BSViewController_iPhone" bundle:nil];
} else {
self.viewController = [[BSViewController alloc] initWithNibName:#"BSViewController_iPad" bundle:nil];
}
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:_viewController];
self.window.rootViewController = navigationController;
[self.window makeKeyAndVisible];
return YES;
}
update 0
Inside (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions, you can add uinavigationcontroller like this:
UIViewController *viewController = … //load your first view controller with the initial xib here
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
self.window.rootViewController = navigationController;
Related
I am new to cocoa development.
When I create a new project on Xcode using storyboards it uses the iOS model, that I like more, of having a viewController and a delegate by those being separate files. Then I start my project using the viewController and adding stuff to its view.
When I create a new project not using storyboards, the "landing page" to start the project is a window and I start by adding views to it.
What I don't like of this model is that I have to add code to the delegate files. I don't like that. I like to have AppDelegate.h and .m just with the coredata and basic code to start the application and pass command to another class.
I simply will not use storyboards anymore on cocoa because they are a sea of bugs and half cooked implementations on Cocoa. NSSavePanel/NSOpenPanel don't work, SplitViewControllers and Tabs work badly. It is a shame.
How do I do that on non-storyboard apps on cocoa? I mean, is it possible to pass control to a viewController or to have another class separate from the app delegate to be the starting point for the app?
Something like this should work:
In main.m do following:
int main(int argc, const char * argv[]) {
AppDelegate * delegate = [[AppDelegate alloc] init];
[[NSApplication sharedApplication] setDelegate:delegate];
[NSApp run];
}
In AppDelegate.m following:
#interface AppDelegate ()
#property (nonatomic,strong) NSWindow *window;
#property (nonatomic,strong) MainViewController *masterViewController;
#end
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
self.masterViewController = [[MainViewController alloc] initWithNibName:#"MainViewController" bundle:nil];
self.window = [[NSWindow alloc] initWithContentRect:NSMakeRect(200, 200, 200, 200)
styleMask:NSResizableWindowMask
backing:NSBackingStoreBuffered
defer:NO];
[self.window.contentView addSubview:self.masterViewController.view];
self.masterViewController.view.frame = ((NSView*)self.window.contentView).bounds;
[self.window makeKeyAndOrderFront:NSApp];
}
This will give you resizable view controlled by MainViewController. You will need to create that class and configure it either with XIB or without. You can remove MainMenu.xib from target setting as main interface and from project.
I am still newbie for IOS Developing, i want to create a login page by MoralViewcontroller.
AppDelegate.h
#interface AppDelegate : UIResponder <UIApplicationDelegate>{
UITabBarController *tabBarController; }
#property (nonatomic,retain) IBOutlet UITabBarController * tabBarController
AppDelegate.m
(void)applicationDidFinishLaunching:(UIApplication *)application
{
// Override point for customization after app launch
[window addSubview:tabBarController. view];
[window makeKeyAndVisible];
LoginViewController *loginView=[[LoginViewController alloc]initWithNibName:#"LoginViewController" bundle:nil];
[tabBarController.view presentModelViewcontroller: loginView animated:YES];
}
However, the login view cannot be shown, I think I define wrongly for tabBarController, but I don't know what wrong with it. Can anyone please advise me? I am doing IOS 5.
Thanks alot..
I'd present a loginView controller from the rootView of the tabBarController.
-(void)viewDidLoad
{
//You can also do this inside a conditional statement, if needed
LoginViewController *loginView=[[LoginViewController alloc]initWithNibName:#"LoginViewController" bundle:nil];
[self.view presentModelViewcontroller:loginView animated:YES];
}
And here is the second way
AppDelegate.h
#interface AppDelegate : UIResponder {
LoginViewController *loginView;
}
#property (nonatomic,retain) LoginViewController *loginView;
AppDelegate.m
-(void)applicationDidFinishLaunching:(UIApplication *)application
{
// Override point for customization after app launch
self.loginView=[[LoginViewController alloc]initWithNibName:#"LoginViewController" bundle:nil];
[window addSubview:loginView. view];
[window makeKeyAndVisible];
}
LoginViewController.m
Call this method on successful login.
-(IBAction)login:(id)sender
{
//init tabbar with subviews;
UITabBarController *tabBarController = [[UITabBarController alloc] initW....];
[self.view addSubview:tabBarController.view];
}
I prefer first method, because in that you will be retaining the tabBarController in AppDelegate.
First of all you have to add the Loginviewcontroller to the window.And then you have to add the tabbarcontroller to the LoginViewController when the login button clicked.
Still new to iOS programming, and despite copious amounts of research, I have run in to another roadblock.
What I want to implement:
I want a UITabBarController that gets loaded when I navigate from the main UI. I would also like to use a NIB to define its properties.
All of the examples I can find put the UITabBarController in the AppDelegate, but I would not like to load it unless it gets used. I also dont know if all of the UIGestureRecognizers would remain active if I just did it modally (I cant get a working implementation).
What I have so far
First, I load an initial loading view from AppDelegate
AppDelegate.h
#class InitialViewController;
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) UIViewController *viewController;
#end
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[InitialViewController alloc] initWithNibName:#"InitialViewController" bundle:nil];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
From this view, as I am just making a skeleton of the UI, I have two buttons, one goes to what would be the main interface, and the other to the UITabBarController.
InitialViewController.h
#interface InitialViewController : UIViewController
- (IBAction)toMain:(id)sender;
- (IBAction)toTabs:(id)sender;
#property (strong, nonatomic) UIViewController *mviewController;
#property (strong, nonatomic) UIViewController *tviewController;
#end
InitialViewController.m
- (IBAction)toMain:(id)sender {
self.mviewController = [[MainViewController alloc] initWithNibName:#"MainViewController" bundle:nil];
[[[UIApplication sharedApplication] delegate] window].rootViewController = self.mviewController;
}
- (IBAction)toTabs:(id)sender {
self.tviewController = [[tabViewController alloc] initWithNibName:#"tabViewController" bundle:nil];
[[[UIApplication sharedApplication] delegate] window].rootViewController = self.tviewController;
}
On loading MainViewController, it behaves exactly like I want. But when I load the tab view, I get one long tab at the bottom and a black background. I can add in things in viewdidload, like changing the background color, but no actual tabs or views linked to the tabs in the XIB.
I suspect there is something I am missing in two areas: in the tab .h, and some linking associated with that in interface builder. Or setting a new rootViewController isnt enough.
tabBarController.h
#import <UIKit/UIKit.h>
#interface iPodViewController : UITabBarController <UITabBarControllerDelegate>
#end
If someone can point me in the right direction and/or show me an implementation that works, I would be most grateful.
-- as a note, when I go in to the tabbar.xib, and use the assistant editor, it opens InitialViewController.h --
Unlike other view controllers (e.g. UITableViewController) you should not subclass the UITabViewController. Therefore, unlike you other view controllers, you don't subclass and then make your subclass the owner of the nib, pointing at the view in the nib, with a customised view.
Instead, for whichever class that you want to own your UITabBarController, add a plain, vanilla UITabBarController as an outlet property on this class. (e.g. your app delegate).
Then create a nib file and drag a UITabBarController object into the nib. Set the owner of the nib to be the class that you want to own your tab bar controller (e.g. your app delegate) and connect the outlet you created as a property to the tab bar controller in the nib.
#interface myTabOwningClass
#property (strong, nonatomic) IBOutlet UITabBarController myTabBarControllerOutlet;
Now at the point you want to create and display your tab bar controller, use the following method:
[[NSBundle mainBundle] loadNibNamed:#"MyTabControllerNib" owner:myTabOwningClass options:nil];
This will initialise the property (i.e. myTabBarControllerOutlet in our example) on the owning class and load the tab bar controller from the nib, including all sub view controllers for each tab etc. that you have defined in the nib.
In a view of my program I have a button and with this button I open a subview; this subview is a view with a tableview. I want go to another view when I push a row of the tableview so I want to make this with a navigation controller; how can I do this?
Your table view delegate will receive a tableView:didSelectRowAtIndexPath: message when you click on one of the table's rows.
You can put there your code to create the UINavigationController and push on to it your new view.
This sample code (from another answer of mine on S.O.) shows how you can do that:
UINavigationController* navigation = [[UINavigationController alloc] init];
iVkViewController *overviewViewController = [[iVkViewController alloc] init];
overviewViewController.title = #"First";
[navigation pushViewController:overviewViewController animated:NO];
This should help you getting things on track.
One side note: you might think of having a navigation controller from the very start, this would make your UI more "well-behaved", but this depends ultimately on your app requirements.
If UIViewController addSubView a view of UITableViewController,you want to push in the method of tableView:didSelectRowAtIndexPath,you should check if self.navigationController is nil. If it's nil,You probably should use
[self.parentViewController.navigationController pushViewController:controller animated:YES];
if self.parentViewController is also nil,Sometimes,you have to set a #property to point out the parentViewController In UITableViewController,like:
#property (nonatomic, weak) UIViewController *parentVC;
and in UIViewController:
UITableViewController *tableViewVC = [[UITableViewController alloc] init];
tableViewVC.parentVC = self;
In UITableViewController ,-tableView:didSelectRowAtIndexPath:
[self.parentVC.navigationController pushViewController:controller animated:YES];
In the iPad Programming Guide, it gives the following code example for specifying the two views (firstVC and secondVC) that will be used in the SplitView...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
MyFirstViewController* firstVC = [[[MyFirstViewController alloc]
initWithNibName:#"FirstNib" bundle:nil] autorelease];
MySecondViewController* secondVC = [[[MySecondViewController alloc]
initWithNibName:#"SecondNib" bundle:nil] autorelease];
UISplitViewController* splitVC = [[UISplitViewController alloc] init];
splitVC.viewControllers = [NSArray arrayWithObjects:firstVC, secondVC, nil];
[window addSubview:splitVC.view];
[window makeKeyAndVisible];
return YES;
}
but when I actually create a new SplitView project in Xcode, I don't see any code that says the default rootView and detailView views should be added to the SplitView. Where can I find that?
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after app launch
rootViewController.managedObjectContext = self.managedObjectContext;
// Add the split view controller's view to the window and display.
[window addSubview:splitViewController.view];
[window makeKeyAndVisible];
return YES;
}
I'm new to iPhone OS programming and I'm just trying to understand how this all works. Thanks in advance for all your help! I'm going to continue researching this question right now.
It's because the links are set up in the *.nib file already. You could still use the .viewControllers approach if you don't want to rely on the *.nib to do it automatically.