I have following structure in my iOS app:
RootViewController (table view controller showing core data).
On RootViewController is a view including 4 buttons.
Button 1: Menu...
After pressing button 1, NSManagedObjectContext is passed to MenuViewController.
On MenuViewController there are several buttons, one of them is used to open DoneViewController, which is a duplicate from RootViewController (only NSPredicates changed to show different core data objects.
DoneViewController is showing correctly the expected rows, but it was supposed to have a navigation bar, which is not shown.
This is the code used to open DoneViewController:
- (IBAction)doneToDoaction:(id)sender {
DoneViewController *viewController = [[DoneViewController alloc] init];
viewController.managedObjectContext = [self mainContext];
[self presentViewController:viewController animated:YES completion:nil];
}
What should I do to open the view and have a navigation bar like RootViewController does?
I will now put all the navigation controller instances that are now in my app:
//AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Fetch the data to see if we ought to pre-populate
NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
[self loadFavoriteThingsData];
RootViewController *rootViewController = (RootViewController *)
[navigationController topViewController];
[rootViewController setManagedObjectContext:[self managedObjectContext]];
[window addSubview:[navigationController view]];
[window makeKeyAndVisible];
return YES;
}
//RootViewController
- (IBAction)MenuToDoAction:(id)sender {
MenuViewController *viewController = [[MenuViewController alloc] init];
viewController.mainContext = [self managedObjectContext];
[self presentViewController:viewController animated:YES completion:nil];
}
//MenuViewController
- (IBAction)doneToDoaction:(id)sender {
DoneViewController *viewController = [[DoneViewController alloc] init];
viewController.managedObjectContext = [self mainContext];
[self.navigationController pushViewController:viewController animated:YES];
}
The last doneToDoaction method, as proposed by #EricLee, doesn't throw an exception, but the button action is not executed and the app freezes...
Instead of presenting DoneViewController, you want to push it onto the current navigation controller.
It is the navigation controller (self.navigationController) that has the view containing the navigation bar. Pushing a view controller onto it will cause that view controller's view to appear, along with the navigation bar, inside the navigation controller's view.
Add navigation controller when present view controller
- (IBAction)doneToDoaction:(id)sender {
DoneViewController *viewController = [[DoneViewController alloc] init];
viewController.managedObjectContext = [self mainContext];
UINavigationController * nVC=[[UINavigationController alloc] initWithRootViewController:viewController];
[self presentViewController:nVC animated:YES completion:nil];
}
If you use storyboard or xib and do not want to push DoneViewController to UINavigationViewController, I suggest you to make a gap for status bar manually in storyboard or xib.
In iOS7, the status bar is transparent. therefore, the top of your VC is extended under it.
If you push it to UINavigationViewController and navigation bar is opaque, there is nothing to do. But, if you don't do that, set a gap manually.
EDIT
Sorry, I found another way better than what I suggest you before. You don't need transparent status bar, set status bar style option to Black Opaque in General tab in project configuration.
You can just push the To-be-presented viewController into the current( presenting) viewcontroller's navigationController.
- (IBAction)doneToDoaction:(id)sender {
DoneViewController *viewController = [[DoneViewController alloc] init];
viewController.managedObjectContext = [self mainContext];
[self.navigationController pushViewController:viewController animated:YES];
}
In your AppDelegate didFinishLaunchingWithOptions
self.window = [[UIWindo walloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.controller = [[ViewController alloc] init];
UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:self.controller];
self.window.rootViewController = nav;
[self.window addSubview:nav.view];
[self.window makeKeyAndVisible];
Related
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
TabBarController *tabBarController = [[TabBarController alloc] init];
UIViewController *vc2 = [[SearchPageControllerViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:vc2];
NSArray *viewControllers = [NSArray arrayWithObjects:navController, vc2, nil];
[tabBarController setViewControllers:viewControllers];
}
I use push segue connection, i have got tab bar but when i change screen with push segue tab bar get invis how can fix this problem i added this code part but now worked any idea ?
Check images for more info...
Make sure you have not checked the "Hide bottom bar on push" option on the Attribute Inspector of the view controllers on Storyboard.
To avoid tabbar from disappearing while changing viewController I would used presentViewController, and dismissViewController instead.
UIViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"testview"];
[self presentViewController:controller animated:YES completion:NULL];
UIViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"rootVC"];
[self dismissViewController:controller animated:YES completion:NULL];
I try to push a UIViewController onto a UINavigationController. The NavigationBar changes (i.e. a back-button appears) but the view is not pushed (*).
I have a UITabBarController as my applications RootViewController.
When I switch to another tab and then switches back, the view (*) gets pushed.
I have never seen this behaviour before. My problem is exactly the same as this, however the methods that solved that issue did not solve mine.
Initially
After I press the row
I understand that this question might be related to issues in AppDelegate, therefore i post the code I use.
Code:
in AppDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
[MagicalRecord setupCoreDataStackWithStoreNamed:#"DBModel"];
/* CONTACTS LIST CONTROLLER */
BoonContactListViewController *contactListViewController = [[BoonContactListViewController alloc] initWithNibName:nil bundle:nil];
UINavigationController *contactListNavigationController = [[UINavigationController alloc] initWithRootViewController:contactListViewController];
[contactListNavigationController setValue:[[BoonNavigationBar alloc]init] forKeyPath:#"navigationBar"];
contactListNavigationController.tabBarItem.title = [NSLocalizedString(#"CONTACTS", nil) capitalizedString];
contactListNavigationController.tabBarItem.image = [UIImage imageNamed:#"menu_contacts.png"];
/* INVITATIONS */
BoonInvitationListViewController *invitationListController = [[BoonInvitationListViewController alloc] initWithNibName:nil bundle:nil];
UINavigationController *invitationNavigationController = [[UINavigationController alloc] initWithRootViewController:invitationListController];
[invitationNavigationController setValue:[[BoonNavigationBar alloc]init] forKeyPath:#"navigationBar"];
invitationNavigationController.tabBarItem.title = [NSLocalizedString(#"SETTINGS", nil) capitalizedString];
invitationNavigationController.tabBarItem.image = [UIImage imageNamed:#"menu_invitations.png"];
/* SETTINGS */
BoonSettingsViewController *settingsViewController = [[BoonSettingsViewController alloc] initWithNibName:nil bundle:nil];
UINavigationController *settingsNavigationController = [[UINavigationController alloc] initWithRootViewController:settingsViewController];
[settingsNavigationController setValue:[[BoonNavigationBar alloc]init] forKeyPath:#"navigationBar"];
settingsNavigationController.tabBarItem.title = [NSLocalizedString(#"SETTINGS", nil) capitalizedString];
settingsNavigationController.tabBarItem.image = [UIImage imageNamed:#"menu_settings.png"];
/* TAB BAR */
BoonTabBarViewController *tabBarController = [[BoonTabBarViewController alloc] init];
tabBarController.viewControllers = #[contactListNavigationController, invitationNavigationController, settingsNavigationController];
[self.window setRootViewController:tabBarController];
[self.window makeKeyAndVisible];
[tabBarController showLogin];
return YES;
}
EDIT:
In the viewController that i am trying to push, neither viewWillAppear, viewDidLoad nor viewDidAppear is called.
If I use presentViewController: animated: completion: I get the preferred behaviour, id rather not though
EDIT 2
How I push my new VC
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
BoonContactInfoViewController *contactInfoViewController = [[BoonContactInfoViewController alloc] initWithNibName:nil bundle:nil];
NSLog(#"NAV %#", self.navigationController);
[self.navigationController pushViewController:contactInfoViewController animated:YES];
}
EDIT 3
It is only the initial tab that cannot push ... if i swap places of the first and second tab, i can push a view controller using in the way i do above.
EDIT 4
It works if i (in my tabBarController) calls
self.selectedIndex = 1;
self.selectedIndex = 0;
EDIT 5
- (void)showLogin
{
if([BoonUserHandler getLogin].length > 0 && [BoonUserHandler getPassword].length > 0){
return;
}
BoonWelcomeViewController *welcomeWC = [[BoonWelcomeViewController alloc] initWithNibName:nil bundle:nil];
UINavigationController *welcomeNavigationController = [[UINavigationController alloc] initWithRootViewController:welcomeWC];
[welcomeNavigationController setNavigationBarHidden:YES];
[self presentViewController:welcomeNavigationController animated:NO completion:nil];
}
What version of iOS are you developing for?
I'd first ask why you're hacking in a nav bar using:
[settingsNavigationController setValue:[[BoonNavigationBar alloc]init] forKeyPath:#"navigationBar"];
rather than the iOS5+ UINavigationController method:
- (instancetype)initWithNavigationBarClass:(Class)navigationBarClass toolbarClass:(Class)toolbarClass
But my overall suggestion would be to remove all this code and use a storyboard. This looks like the perfect opportunity.
I think you are getting wrong Navigation controller to push that's why it showing this problem..
You have to fetch right navigation controller from tab controller
self.tabBarController.selectedIndex = 0;
just change tab controller selected index
I'm new to Objective-C and I want to add a UINavigationBar on my CatrgoryBIDViewController. I have proceed UIButton in InstructionBIDViewController.m file that should navigate to CatrgoryBIDViewController. Here is the function code:
- (IBAction)proceed:(id)sender {
viewControllercat =
[[CatrgoryBIDViewController alloc]
initWithNibName:#"CatrgoryBIDViewController"
bundle:nil];
UINavigationController *nav =
[[UINavigationController alloc]
initWithRootViewController:self.viewControllercat];
//[self.navigationController pushViewController:viewControllercat animated:YES];
[self.navigationController setNavigationBarHidden:NO animated:YES];
}
But it is not setting the UINavigationBar.
You should read the documentation here to understand the way a NavigationController is working. For your case:
If your current ViewController (where your proceed-method is implemented) has a NavigationController (is child of it), you can push another ViewController onto the stack of that NavigationController with
[self.navigationController pushViewController:viewControllercat animated:YES];
In this case you do not need to initialize another NavigationController, but in your CatrgoryBIDViewController in viewWillAppear you need to make the NavigationBar visible if it was not before already with
[self.navigationController setNavigationBarHidden:NO animated:YES];
If your current ViewController does not have a NavigationController, you can not push another ViewController on top of it and can not show the NavigationBar of it (although you can create your own NavigationBar and add it to the View of the ViewController, but without the usual Navigation-behaviour embedded).
If you open your ViewController programmatically (e. g. from the AppDelegate) you are correct to do so by your call:
viewControllercat = [[CatrgoryBIDViewController alloc] initWithNibName:#"CatrgoryBIDViewController" bundle:nil];
UINavigationController *nav=[[UINavigationController alloc] initWithRootViewController:self.viewControllercat];
My apologies - After having reread your question, I am going to tweak my answer some.
-(IBAction)proceed:(id)sender
{
viewControllercat = [[CatrgoryBIDViewController alloc] init];
UINavigationController * nc =
[[UINavigationController alloc] initWithRootViewController:vc];
// We now need to display your detail view but cannot push it.
// So display modally
[self presentViewController:nc animated:YES completion:Nil];
}
The above should result in your DetailViewController - CategoryBIDViewController being displayed on top of your InstructionBIDViewController and it should have a UINavigationController in it.
I am working on a project that uses CoreData one-to-many relationship between folder and files. To show this I am using UISplitViewController, Folders are shown on MasterView and on click of each folder the files are shown on DetailView.Both folders and files are added dynamically.
I have programatically created UISPlitViewController this way
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
FolderViewController = [[FolderViewController alloc] initWithNibName:#"FolderViewController_iPad" bundle:nil];
UINavigationController *masterNavigationController = [[UINavigationController alloc] initWithRootViewController:FolderViewController];
FolderViewController.managedObjectContext = self.managedObjectContext;
fileViewController = [[fileViewController alloc] initWithNibName:#"fileViewController_iPad" bundle:nil];
UINavigationController *detailNavigationController = [[UINavigationController alloc] initWithRootViewController: fileViewController];
FolderViewController.fileViewController = fileViewController;
self.splitViewController = [[UISplitViewController alloc]init];
self.splitViewController.delegate = fileViewController;
self.splitViewController.viewControllers = #[masterNavigationController, detailNavigationController];
self.window.rootViewController = self.splitViewController;
}
This splits my ipad in to two. Leftside is FolderViewController and rightside is FileViewController.
My master View never hides, in any Orientation.
I have a button on both Master and DetailView which opens common EditViewController modally through splitViewController this way
- (void)Buttonclick
{
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
testViewController = [[EditViewController alloc] initWithNibName:#"EditViewController" bundle:nil];
m_editViewController.modalPresentationStyle = UIModalPresentationFormSheet;
[appDelegate.splitViewController presentModalViewController:m_editViewController animated:YES];
}
and when I dismiss this View, I add folders or files accordingly.
I dismiss this view this way
[self dismissModalViewControllerAnimated:YES];
I have few doubts here
1) When I launch the app, all imp(main) functions from Both View Controller gets called.is that ok?
2) When I dismiss this ModalView when opened from DetailView, the delegate functions of NSFetchResultsController get called, which are in MasterView . is that ok?
3) As those functions are getting called, my logic fails in some situations.
Regards
Ranjit
I'm experimenting with OAuth 2.0. which brings up a window containing a UIWebView as a canvas for the authentication server to communicate through. Right now, it is being shown as a modal view with its own view controller, and doesn't have a back button or cancel button. So the user has no way to escape from the sign-in process.
I want to have the webView handled by a navigation controller so I can push the webView's view controller.
I am having problems with doing this. It seems to me I should be able to just create a UINavigationController object with the root view controller being the main view controller, like this
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:self];
However, this line crashes the program without any error message in the debugger.
I thought I could place a line to push the web view controller immediately after the line above, like this:
[navController pushViewController:windowController animated:YES];
But, without getting past the first line, I can't begin to work out the details on getting the web view to show and then configure the back button.
UPDATE
Here is some context. This is in a single view application. The following code is in the main view controller, which brings up the sign-in dialog. I would like to replace the last line, where the presentModalViewController is called, with a push of the windowController onto a navController stack. Note the commented code at the end, where the initialization of the navigation controller is located.
- (IBAction)signInClicked:(id)sender {
if (![self isSignedIn]) {
// Sign in
[self runSigninThenInvokeSelector:#selector(updateUI)];
}
[self updateUI];
}
- (void)runSigninThenInvokeSelector:(SEL)signInDoneSel {
NSString *clientID = mClientId;
NSString *clientSecret = mClientSecret;
// Show the OAuth 2 sign-in controller
NSString *scope = [GDataServiceGoogleBlogger authorizationScope];
GTMOAuth2ViewControllerTouch *windowController;
windowController = [[GTMOAuth2ViewControllerTouch controllerWithScope:(NSString *)scope
clientID:(NSString *)clientID
clientSecret:(NSString *)clientSecret
keychainItemName:(NSString *)kKeychainItemName
delegate:(id)self
finishedSelector:#selector(windowController:finishedWithAuth:error:)] retain];
//UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:self]; // This causes a crash when it is not commented out.
[self presentModalViewController:windowController animated:YES];
}
The application delegate didFinishLaunchingWithOptions is set up this way:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
self.viewController = [[[blogSpotViewController alloc] initWithNibName:#"myNibName" bundle:nil] autorelease];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
Well, you can present this as a modal controller. You just need to arrange to call dismissModalViewController: in response to a button or some other event on the 'windowController'.
But if you want to use a navigation controller, then you can set that up in application:didFinishLaunchingWithOptions: like so:
// create window here like now
blogSpotViewController *viewController = [[blogSpotViewController alloc] initWithNibName:#"myNibName" bundle:nil];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:viewController];
[viewController release];
// TODO: hold onto this navController in a property if you really need that.
self.window.rootViewController = navController;
[navController release];
// present window here as you are now
This embeds your main view controller in a navigation controller. Then back in your runSigninThenInvokeSelector: you can...
[self.navigationController pushViewController:windowController animated:YES];
Hope that points you in the right direction.