I'm trying to have my app open to a specific ViewController that is deeply embedded in a Navigation Controller, but isn't the RootViewController. I have tried in the app delegate didFinishLaunchingWithOptions adding:
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewController = storyboard.instantiateViewControllerWithIdentifier("NavViewController")
self.window?.rootViewController = initialViewController
self.window?.makeKeyAndVisible()
But this goes to the root view controller. I tried changing this line to:
storyboard.instantiateViewControllerWithIdentifier("MainViewController")
and this does open to the correct viewcontroller but then there is no Navigation Bar on the top which is needed to navigate in the app.
To access the rootViewController from the AppDelegate then here is the code:
let rootViewController = application.windows[0].rootViewController as! UINavigationController
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let notificationVC = mainStoryboard.instantiateViewControllerWithIdentifier("identifier") as! NotificationVC
rootViewController.pushViewController(notificationVC, animated: false)
Now, it will have the navigationBar. Let me know, if you still face the issue. thanks.
Here is the Objective-C version to open a specific UIViewController deeply embedded inside a UINavigationController (which is not the rootController).
If we take #bdc example in comments and we want to open UIViewController D:
A : rootViewController
N : navigationController
B, C, D : UIViewControllers embedded in N
A -> N[B C D]
Set storyboardId in InterfaceBuilder for every UIViewController or UINavigationController in the hierarchy through D.
In AppDelegate, the code is straight forward. You just have to instantiate everything, and use your UINavigationController to push every UIViewController in your hierarchy.
// Instanciate from storyboard with identifiers
UIStoryboard * storyboard = [UIStoryboard storyboardWithName:#"MyStoryboard" bundle:nil];
UINavigationController * N = (UINavigationController*) [storyboard instantiateViewControllerWithIdentifier:#"N"];
UIViewController* B = (UIViewController*) [storyboard instantiateViewControllerWithIdentifier:#"B"];
UIViewController* C = (UIViewController*) [storyboard instantiateViewControllerWithIdentifier:#"C"];
UIViewController* D = (UIViewController*) [storyboard instantiateViewControllerWithIdentifier:#"D"];
// Set up the views hierarchy
self.window.rootViewController = N;
[N pushViewController:B animated:NO];
[N pushViewController:C animated:NO];
[N pushViewController:D animated:YES];
[self.window makeKeyAndVisible];
Hope this will help.
Related
I use storyboard, but want to load viewcontroller from xib file.
In storyboard I remove view.
Call to open viewcontroller:
- (void)SettingsButtonClick:(id)sender
{
CopyViewController* vc;
vc = [[CopyViewController alloc] initWithNibName:#"CopyViewController" bundle:nil];
[self.navigationController pushViewController:vc animated:YES];
}
But navigationcontroller hides part of my view. How can I arrange my View to start its frame below navigationcontroller?
self.view.frame = CGRectMake(0, 200, 100, 200); in viewDidLoad doesn't help me :-(
I have found solution
self.edgesForExtendedLayout = UIRectEdgeNone;
I am trying open a view that is in storyboard from code and i don't know how open this. In objective c was
UIViewController *controller = [[UIViewController alloc]
initWithNibName:#"myXib" bundle:[NSBundle mainBundle]];
[self.storyboard instantiateViewControllerWithIdentifier:#"myView"];
But I don't know how to make this in Swift.
I have my code outlet declaration and I use this:
#IBOutlet var viewAboutUs : UIView = UIView()
UIView.animateWithDuration(0.2, animations: {
self.viewAboutUs.frame = CGRectMake(0, UIScreen.mainScreen().bounds.size.height, UIScreen.mainScreen().bounds.size.width, 260.0)
But with this code, my app crash. How can open this view from code??
Try something like this:
let controller1 = UIViewController(nibName: "myXib", bundle: nil);
let storyboard = UIStoryboard(name: "myStoryboard", bundle: nil)
let controller2 = storyboard.instantiateViewControllerWithIdentifier("myView") as UIViewController
I'm building a collection of forms each of which contains several fields. Some of the fields are UITextFields that will display a date. I've created a new class called DatePickerTextField, a descendant of UITextField. When a DatePickerTextField is tapped I'd like for a UIDatePicker control to appear in a popover.
My question is how do I use the storyboard to implement the popover? I can do a segue when there is a specific, visible control in the scene. But how do I represent a generic popover in the scene that I can attach to any instantiated DatePickerTextField that becomes active?
You can create segue that is not connected to any control but I don't think that there would be way to specify anchor point for popover from code. Another option is to create ViewController that is not connected with any segue. When editing storyboard, create ViewController which will be placed in popover, select it and navigate to Utilities pane->Attributes Inspector. Set Size to Freeform, Status Bar to None, specify unique Identifier that will be used to instantiate ViewController from code. Now you can change the size of ViewController by selecting its View and navigating to Utilities pane->Size Inspector.
After that you can create popover from code:
- (IBAction)buttonPressed:(id)sender {
UIView *anchor = sender;
UIViewController *viewControllerForPopover =
[self.storyboard instantiateViewControllerWithIdentifier:#"yourIdentifier"];
popover = [[UIPopoverController alloc]
initWithContentViewController:viewControllerForPopover];
[popover presentPopoverFromRect:anchor.frame
inView:anchor.superview
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
One caveat is that you need to hold reference to popover as ivar of your class, otherwise it'll crash because UIPopoverController would be released and deallocated after buttonPressed returns:
#interface MyViewController : UIViewController {
// ...
UIPopoverController *popover;
// ...
}
So, I had a similar issue, and in case others might benefit, I figured I'd share it, since I benefit so much from stackoverflow.
This solution allows you to set the anchor of a customizable popover segue. It also allows you to configure the segue to be modal or not (I could not find a way to prevent the segue by dimming the exterior context, so if someone knows how to do that, I would be interested in hearing it); this is accomplished by setting the passthrough views for the popover controller. I also added the capacity to specify a custom view, rather than the view of the source viewcontroller (since I needed this capacity); this portion is not critical to the solution.
DynamicPopoverSegue.h
#interface DynamicPopoverSegue : UIStoryboardPopoverSegue
#property BOOL isModal;
#property UIView* sourceView;
#property CGRect anchor;
#end
DynamicPopoverSegue.m
#implementation DynamicPopoverSegue
- (void)perform
{
if (!self.popoverController.popoverVisible)
{
UIViewController* dst = (UIViewController*)self.destinationViewController;
UIViewController* src = (UIViewController*)self.sourceViewController;
UIView* inView = _sourceView ? _sourceView : src.view;
self.popoverController.contentViewController = dst;
if (!_isModal)
{
[self.popoverController setPassthroughViews:[[NSArray alloc] initWithObjects:inView, nil]];
}
[self.popoverController presentPopoverFromRect:_anchor
inView:inView
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
}
}
#end
Then you just set your segue to "Custom" in the storyboard, and set the segue class to "DynamicPopoverSegue". In my case, since I wanted to associate it with dynamic layers in a view, I could not set the anchor, so I created the segue by control clicking from the view controller icon in the bar beneath my view controller to the view controller I was using to present the popupover.
To call the popover segue:
[self performSegueWithIdentifier:#"MyPopoverSegue" sender:self];
And to configure the popover segue:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"MyPopoverSegue"])
{
DynamicPopoverSegue* popoverSegue = (DynamicPopoverSegue*)segue;
// set the anchor to wherever you want it to be
popoverSegue.anchor = _destinationFrame;
}
}
- (IBAction)pressItemChooseOprateRoom:(id)sender {
if (isPad){
// UIView *anchor = sender;
UIViewController *viewControllerForPopover =
[self.storyboard instantiateViewControllerWithIdentifier:#"OperateRoomList"];
_myPopover = [[UIPopoverController alloc]
initWithContentViewController:viewControllerForPopover];
CGRect rc=[self getBarItemRc:sender];
[_myPopover presentPopoverFromRect:rc
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
[MLControl shared].popover =self;
// [self perfformSegueWithIdentifier:SEGUE_POP_OPERATEROOM sender:self];
}else{
[self iphoneOpenOperateRoomList];
/* [self performSegueWithIdentifier:#"iPhonePushOperateRoom" sender:self];
*/
}
}
-(void)iphoneOpenOperateRoomList{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"OperateRoomList"];
// if (!index.showTabBar) {
// vc.hidesBottomBarWhenPushed = YES;
// }
[self.navigationController pushViewController:vc animated:YES];
}
Just used the answer from Jonnywho for my SWIFT project. In case you need it:
Here's the SWIFT version:
let anchor: UIView = sender
var viewControllerForPopover = self.storyboard?.instantiateViewControllerWithIdentifier("GameAboutViewController") as! UIViewController?
let popover = UIPopoverController(contentViewController: viewControllerForPopover!)
popover.presentPopoverFromRect(anchor.frame, inView: anchor, permittedArrowDirections: UIPopoverArrowDirection.Any, animated: true)
Add a UIView in the scene dock.
You can add it as a subview to any existing view on the view controller.
You can then toggle it's isHidden property as you require.
You can add multiple such subviews and create many such popups.
This technique will save you from setting up a new View Controller and using segues.
My DetailView of a SplitView has a Map with Annotations. Upon clicking an Annotation the entire window (and not just the DetailView) should go to another view. Unfortunately that doesn't work.
This is how I'm creating my NavigationController in my AppDelegate
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
[self.window addSubview:navigationController.view];
This is how I'm creating the SplitView
left = [[MapSplitViewLeft alloc] initWithStyle:UITableViewStylePlain];
right = [[MapViewController alloc] init];
splitViewController = [[UISplitViewController alloc] init];
splitViewController.viewControllers = [NSArray arrayWithObjects:left,right, nil];
self.view = splitViewController.view;
left.right = right;
[left release];
[right release];
And that's what's being called when clicked on an Annotation:
- (void)showDetails:(id)sender {
NSLog(#"Yes it works");
VenueViewController *vviewcontroller = [[VenueViewController alloc]
initWithNibName:#"VenueViewController" bundle:[NSBundle mainBundle]];
AppDelegate *del = (AppDelegate *)[UIApplication sharedApplication].delegate;
[del.navigationController pushViewController:vviewcontroller animated:YES];
}
When I click on the Annotation I only get "Yes it works" but nothing else is happening.
Thanks so much for any advise.
Every UIViewController has the property "navigationController". Try with your current ViewController to push the new Viewcontroller.
[self.navigationController pushViewController:vviewcontroller animated:YES];
edit: Sorry, you mean the entire window! I think that would not work.
edit2: Maybe this answer can help you how to add a view over window in uiviewcontroller But i think thats that view is not on your navigationController-Stack
I have a problem, I have created a project window based application in xcode, then I create a UITabBarController that manages two views all programmatically, the second view is a tableView and I want to see in the top a UINavigationController, I have tried a lot but I don't know how to have a UINavigationController in the second view. this is the code:
ProjectAppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//Creo una tabBarController
UITabBarController *tabBarController = [[UITabBarController alloc] init];
//Create the two view controllers
UIViewController *vc1 = [[Visuale1ViewController alloc] init];
UIViewController *vc2 = [[Visuale2ViewController 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];
//Setto la tabBarController come rootViewController di window
[window setRootViewController:tabBarController];
//The window retain tabBarController, possiamo lasciare il nostro riferimento
[tabBarController release];
[self.window makeKeyAndVisible];
return YES;
}
Visuale1ViewController.h
#implementation Visuale1ViewController
- (id)init{
[super initWithNibName:#"Visuale1ViewController" bundle:nil];
//Get the tab bar item
UITabBarItem *tbi = [self tabBarItem];
//Give it a label
[tbi setTitle:#"Visuale 1"];
return self;
}
// The designated initializer. Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
- (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)bundle {
return [self init];
}
Visuale2ViewController.h
#implementation AnswerViewController
- (id)init{
//Call the superclass's designated initializer
/*[super initWithNibName:nil
bundle:nil];*/
[super initWithStyle:UITableViewStyleGrouped];
answers = [[NSMutableArray alloc] init];
for (int i = 0; i<10 ; i++) {
[answers addObject:[Answer DefaultAnswer]];
}
//Get the tab bar item
UITabBarItem *tbi = [self tabBarItem];
//Give it a laber
[tbi setTitle:#"Visuale 2"];
return self;
}
- (id)initWithStyle:(UITableViewStyle)style{
return [self init];
}
//All below are all methods to work the table view, and all go well, the only problem it's the UINavigationController, to manage then the detail of the table...
Now I want to know how I can put a UINavigationController in the second view. I try do this, in ProjectAppDelegate.m:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//Creo una tabBarController
UITabBarController *tabBarController = [[UITabBarController alloc] init];
//Create the two view controllers
UIViewController *vc1 = [[Visuale1ViewController alloc] init];
UIViewController *vc2 = [[Visuale2ViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:vc2];
//Make an array containing the two view controllers
NSArray *viewControllers = [NSArray arrayWithObjects:vc1, navController, 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];
//Setto la tabBarController come rootViewController di window
[window setRootViewController:tabBarController];
}
In this way I can visualize the NavigationBar, but I lost the name of the SecondTabBar. Sorry for my english, how I can do this?
Yes in the second view you have to set title as
[self.navigationItem setTitle:#"Visuale2"];
For TabBar title-
UITabBar *tabBar = [self.tabBarController tabBar];
NSArray *tabBarItems = [tabBar items];
UITabBarItem *secondTabBarItem = [tabBarItems objectAtIndex:1];
[secondTabBarItem setTitle:#"Visuale2"];
I left the code as it was and I added in init Visale2ViewController this:
UIImage *i = [UIImage imageNamed:#"Hypno.png"];
[tbi setImage:i];
and now in can see the text Visuale2 in tabBar and the image...i don't know why...
You need to set the tabBarItem property for your UINavigationController. Something like this.
UITabBarItem *tabItem = [[UITabBarItem alloc] initWithTitle:#"Visuale 2" image:nil tag:1];
UIViewController *vc2 = [[Visuale2ViewController alloc] init];
navController = [[UINavigationController alloc] initWithRootViewController:vc2];
navController.tabBarItem = tabItem;
After looking at it,the scenario seems to be same like me.What I faced for the first time when doing Tab+Navigation.
I am sure that there is some problem with your Tab+Navigation based application. Although it shows the Tab as well as navigation are not able to navigate the basic flow.And it is very difficult to solve your problem with such less code.
Instead of this, I had an alternate solution for the same:
Once you have a tab bar in a XIB, the easiest way to approach this is to drag a UINavigationController object over from the Library window (looks like a left nav bar button on a gold background) into the Tree View for your tab bar (the text only view, not the GUI). Place it under the tab bar, then drag your existing view controller under the tab bar controller instead of under the tab bar.
When you go to view that tab you should then see a navigation bar on the top of it... if you are loading the navigation controller from another xib, you'll modify the nav bar in the tab bar xib.
else you can below you can follow the best url for the same:
http://books.google.co.in/books?id=2yYlm_2ktFYC&pg=PA179&lpg=PA179&dq=navigation+with+the+tab+based+application+iphoneSDK&source=bl&ots=nf2YYjX5Am&sig=COpHj9wOtsDChQBglpsljSTsElw&hl=en&ei=3ZoFTeGSOI_tsgbc_Iz6CQ&sa=X&oi=book_result&ct=result&resnum=6&ved=0CDAQ6AEwBQ#v=onepage&q&f=false
http://www.youtube.com/watch?v=LBnPfAtswgw
Hope this will surely solve your problem.