I have a splitview-based app, that has a popover menu containing 3 views. I would like to add another view, that doesn't appear in the popover menu, and is displayed when a different button is clicked.
Here is a screenshot, with the popover menu, and the 'Log' button which I want to use to display my new view.
All of the other views are configured something like this:
UIViewController <SubstitutableDetailViewController> *detailViewController = nil;
if (row == 0) {
FirstDetailViewController *newDetailViewController = [[FirstDetailViewController alloc] initWithNibName:#"FirstDetailView" bundle:nil];
detailViewController = newDetailViewController;
}
...
NSArray *viewControllers = [[NSArray alloc] initWithObjects:self.navigationController, detailViewController, nil];
splitViewController.viewControllers = viewControllers;
[viewControllers release];
I tried to replicate this code for my new view:
-(void)displayLogView{
UIViewController <SubstitutableDetailViewController> *detailViewController = nil;
LogDetailViewController *newDetailViewController = [[LogDetailViewController alloc] initWithNibName:#"LogDetailViewController" bundle:nil];
detailViewController = newDetailViewController;
// Update the split view controller's view controllers array.
NSArray *viewControllers = [[NSArray alloc] initWithObjects:self.navigationController, detailViewController, nil];
splitViewController.viewControllers = viewControllers;
[viewControllers release];
[detailViewController release];
}
But nothing happens. I think that I am missing the code to actually display the view. I tried to find how the other views were displayed, but could not find anything (I got the code from the apple sample code).
Any help would be appreciated!
If you just want a slide-over view try using presentModalViewController to show it and dismissModalViewController to get rid of it.
Related
I have a view controller named ViewController.
ViewController displays a UIView that has a button on it, which allows me to advance to a second view controller - SecondViewController.
SecondViewController also has a button on it, which allows me to advance to a third view controller.
However, I am having trouble displaying ThirdViewController. When I tap the button in SecondViewController it throws an error:
Warning: Attempt to present ... on ... whose view is not in the window hierarchy!
I have been to a bunch of other sites and posts that address this issue, but cannot seem to find a working solution. I have implemented quite a few solutions, but none seem to work.
Here is my code:
- (void)secondaryView:(UIView *)secondaryView
{
UIView *theView = secondaryView;
UIViewController *viewController = [[UIViewController alloc] init];
viewController.view.frame = [UIScreen mainScreen].bounds;
[viewController.view addSubview:theView];
viewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentViewController:viewController animated:YES completion:nil];
}
secondaryView is a UIView that I am constructing elsewhere in the application. I add it to the viewController then present the viewController.
Is there any way to dynamically create UIViewControllers, add a UIView to each one, and add them to the window hierarchy?
If you can use navigation in your ViewControllers, you can try the below code
In the place where you call the firstViewController,
-(void)callFirst
{
FirstViewController *first = [FirstViewController alloc] init];
UINavigationController *navigationController = [UINavigationController alloc] initWithRootViewController:first];
navigationController.modalPresentaionStyle = UIModalPresenationFormSheet;
[self presentModalViewController:navigationController animated:YES];
}
And in the FirstViewController button action ,you can write
-(void)callSec
{
SecondViewController *sec = [SecondViewController alloc] init];
[self.NavigationController pushViewController:sec animated:YES];
}
And in SecondViewController you can do the same
-(void)callThird
{
ThirdViewController *third = [ThirdViewController alloc] init];
[self.NavigationController pushViewController:third animated:YES];
}
Try this...And in these ViewControllers you can do whatever coding you want to meet the requirement like
-(void)viewDidLoad
{
UIView *newView = [[UIView alloc] initWithFrame:CGRectMake(20,20,400,400)];
newView.backGroundColor = [UIColor redColor];
[self.view addSubView:newView];
}
I implemented a splitview using 2 UITableViews and a UIViewController. Showing both on the screen with their own data is working fine.
Now in my DidSelectRowForIndexPath I did the following:
DetailViewController *nextController = [[DetailViewController alloc] initWithStyle:UITableViewStylePlain];
NSMutableArray *objects;
objects = [[NSMutableArray alloc] initWithObjects:#"A", #"B", nil];
nextController.title = #"Filter";
[nextController SetArray:objects];
UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:nextController];
[self presentModalViewController:nc animated:YES];
//used this before [self.navigationController pushViewController:nextController animated:YES];
[FilterView deselectRowAtIndexPath:indexPath animated:YES];
Maybe you know a better method as what I did to present the nextController
The nextController is always showing up from the bottom and moving to the top. How can I accomplish this default sliding animation where the detail view comes into the view from the right side?
If you have started the app from the master/detail template while creating the project. Then it will have the navigation controller set automatically in the appDelegate didFinishLaunching method so in the didSelect methods you have to just use
`[self.navigationController pushViewController:vc animated:YES];`
instead of
[self presentModalViewController:nc animated:YES];
Here is a sample code which uses split view with navigation to and from root view.
First you need to confirm that you have UINavigationController at base then you can pushViewController:nextController
[FilterView deselectRowAtIndexPath:indexPath animated:YES];
DetailViewController *nextController = [[DetailViewController alloc] initWithStyle:UITableViewStylePlain];
NSMutableArray *objects;
objects = [[NSMutableArray alloc] initWithObjects:#"A", #"B", nil];
nextController.title = #"Filter";
[nextController SetArray:objects];
[self.navigationController pushViewController:nextController animated:YES];
I present a modalViewController that is actually a navigation controller with one view, and a custom navigation bar. The modal view appears fine as expected, but when I attempt to remove it from view using [self dismissModalViewControllerAnimated:YES], I am hitting a "-[UINavigationController modalViewController]: message sent to deallocated instance". Can't seem to figure this out. Any ideas?
Instantiating the ModalViewController:
// Make a navigation controller and add the view inside it
MyViewController *evc=[[MyViewController alloc] initWithNibName:#"MyViewController" bundle:nil];
//UINavigationController *nvc = [[UINavigationController alloc] initWithRootViewController:evc];
UINib *nib = [UINib nibWithNibName:#"UINavigationBarWithBackgroundImage" bundle:nil];
UINavigationController *nvc = [[nib instantiateWithOwner:nil options:nil] objectAtIndex:0];
[nvc setViewControllers:[NSArray arrayWithObject:evc]];
evc.delegate=self;
[evc release];
[self presentModalViewController:nvc animated:YES];
[nvc release];
and trying to remove it. This is where the error comes in:
[self dismissModalViewControllerAnimated:YES];
Not sure about this, but try it anyway:
Remove
[nvc release]
and see if
[self dismissModalViewControllerAnimated:YES];
now works.
Is there a reason you are loading two seperate nibs to show this modal? You do not need to load a nib containing a navigation controller to get this working.
Try something like this:
// Make a navigation controller and add the view inside it
MyViewController *evc= [[MyViewController alloc] initWithNibName:#"MyViewController" bundle:nil];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:evc];
evc.delegate=self;
[self presentModalViewController:navController animated:YES];
[evc release];
[navController release];
I am trying to push in a new view controller with the code:
[self.navigationController pushViewController:webViewController animated:YES];
But its not working. This code happens when you select a cell in my table view. I have a table view which I think is preventing this from happening. I have tried presenting it modally but that gets rid of the navigation bar and i can't go back. There is an extremely similar to this but the answer didn't work for me!
UPDATE
- (void)loadView {
// Create an instance of UIWebView as large as the screen
CGRect screenFrame = [[UIScreen mainScreen] applicationFrame];
UIWebView *wv = [[UIWebView alloc] initWithFrame:screenFrame];
// Tell web view to scale web content to fit within bounds of webview
[wv setScalesPageToFit:YES];
[self setView:wv];
[wv release];
}
puts the web view as the WebViewController's view
there is no nib as shown above
the didSelect cell method IS CALLED using an NSLog to find out
Everything is initialized and allocated and non-zero
UPDATE:
my did select cell method:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Push the web view controller onto the navigaton stack - this implicity
// creates the web view controller's view the first time through
NSLog(#"TOUCHED!");
webViewController = [[WebViewController alloc] init];
if (webViewController == nil) {
NSLog(#"webViewController in nil state");
}
[self.navigationController pushViewController:webViewController animated:YES];
// Grab the selected item
RSSItem *entry = [[channel items] objectAtIndex:[indexPath row]];
// Construct a URL with the link string of the item
NSURL *url = [NSURL URLWithString:[entry link]];
// Construct a request object with that URL
NSURLRequest *req = [NSURLRequest requestWithURL:url];
// Load the request into the web view
[[webViewController webView] loadRequest:req];
// Set the title of the web view controller's navigation item
[[webViewController navigationItem] setTitle:[entry title]];
}
ALL OF THIS WORKED BEFORE INSERTING TAB BAR CONTROLLER
UPDATE
Where I create the controllers (IN APP DELEGATE):
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
ListViewController *lvc = [[ListViewController alloc] initWithStyle:UITableViewStylePlain];
[lvc autorelease];
// Create the tabBarController
UITabBarController *tabBarController = [[UITabBarController alloc] init];
// Create two view controllers
UIViewController *vc1 = [[ListViewController alloc] initWithStyle:UITableViewStyleGrouped];
UIViewController *vc2 = [[YoutubeViewController alloc] init];
// Make an array containing the two view controllers
NSArray *viewControllers = [NSArray arrayWithObjects:vc1, vc2, nil];
// The viewControllers array retains vc1 and vc2, we can release
// our ownership of them in this method
[vc1 release];
[vc2 release];
// Attach them to the tab bar controller
[tabBarController setViewControllers:viewControllers];
// Put the tabBarController's view on the window
[[self window] setRootViewController:tabBarController];
// The window retains tabBarController, we can release our reference
[tabBarController release];
// Show the window
[[self window] makeKeyAndVisible];
return YES;
}
So I really have no idea whats going on here. Also IF YOU COULD PLEASE HELP ME WITH ANOTHER QUESTION! Go to my profile and see the question about how to stop cutoffs/add extra line for text label in uitableviewcell
I don't see the initial UINavigationViewController in your app delegate. In order to use the self.navigationController pushViewController, the view controller needs to be in one of the self.navigationController.viewControllers. Can you modify your code and try the following and see it works for you.
// Create two view controllers
UIViewController *vc1 = [[ListViewController alloc] initWithStyle:UITableViewStyleGrouped];
UIViewController *vc2 = [[YoutubeViewController alloc] init];
// Create the UINavigationController and put the list view controller as the root view controller
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:vc1];
// Make an array containing the two view controllers and the UINavigationController which has the ListViewController is the first one.
NSArray *viewControllers = [NSArray arrayWithObjects:navController, vc2, nil];
// The viewControllers array retains vc1 and vc2, we can release
// our ownership of them in this method
[vc1 release];
[vc2 release];
[navController release];
// Attach them to the tab bar controller
[tabBarController setViewControllers:viewControllers];
There are several points you have to check, in order to make the push successful.
First, the view controller to be pushed is probably designed and stored in a NIB file. Check how you create it in your code, particularly the NIB file name (assuming you use -(id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle). It must be the real NIB filename without the NIB/XIB extension.
Second, is the selection event triggered and the message really sent to the table view delegate ? You could put some logging to ensure that. The table view won't prevent the view controller from being pushed on the navigation stack.
The question isn't really precise on how/where you create that controller, so finally, if none of this works, make the test to alloc/init the controller just before pushing. You might have a better understanding of what is going on.
If the view controller is under the "More" button, then things change a bit.
Here's what worked for me to figure out what navigation controller to use:
- (void)application:(UIApplication *)app didReceiveLocalNotification:(UILocalNotification *)notif {
UITabBarController *tabBar = (UITabBarController*) self.window.rootViewController;
UINavigationController* navigationController = (UINavigationController*)self.tabBarController.selectedViewController;
UIViewController* top = nil;
if ([navigationController respondsToSelector:#selector(topViewController)]) {
top = navigationController.topViewController;
}
// the actual current navigation controller depends on whether we are on a view under the More tab
UINavigationController *curNavController;
if (top == nil) { // this implies a view under the More tab
curNavController = tabBar.moreNavigationController;
} else {
curNavController = navigationController;
}
[[LocalNotificationMgr Get] ReceivedNotification:notif navController:curNavController];
}
Basically if the user is on a view under the More tab, the actual current UINavigationController you want to use to push a UIViewController onto is the UITabBarController's moreNavigationController property.
If on a view actually visible on the tab bar itself, use the UITabBarController's selectedViewController property.
NOTE: if you're on the "More screen" itself, you can use either property.
Did you do it in the manner like below??
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if(reqList==Nil)
{
reqList = [[RequestList alloc]initWithNibName:#"RequestList" bundle:nil];
}
[self.navigationController pushViewController:reqList animated:YES];
}
I try to change the modalTransitionStyle property of my modal view. Every style work except for FlipHorizontal. If I choose this, nothing happens.
I have an UINavigationController which should be flipped in.
Heres the code:
UINavigationController *loginNavCon = [[UINavigationController alloc] init];
loginNavCon.navigationBar.barStyle = UIBarStyleBlack;
// push login view
LogInViewController *liVC = [[LogInViewController alloc] initWithStyle:UITableViewStyleGrouped];
[loginNavCon pushViewController:liVC animated:NO];
[liVC release];
// show login view
loginNavCon.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self.window.rootViewController presentModalViewController:loginNavCon animated:YES];
[loginNavCon release];
Thanks for your help.
Ok, I figured it out!
The point is to set it in the pushing UIViewController, not in the pushed one.
So in my example code it has to look like this:
UINavigationController *loginNavCon = [[UINavigationController alloc] init];
loginNavCon.navigationBar.barStyle = UIBarStyleBlack;
// push login view
LogInViewController *liVC = [[LogInViewController alloc] initWithStyle:UITableViewStyleGrouped];
[loginNavCon pushViewController:liVC animated:NO];
[liVC release];
// show login view
/** changed **/
self.window.rootViewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
/*************/
[self.window.rootViewController presentModalViewController:loginNavCon animated:YES];
[loginNavCon release];