I want to change below code with storyboard with Xcode 4.2.
UIViewController * example = [[ExampleViewController alloc] initWithNibName:#"ExampleViewController" bundle:nil];
Now ExampleViewController.xib file exist.
but I want to make it with storyboard.
please help me.
(I'm not good at English. Sorry)
The UIStoryboard class is your friend:
UIStoryboard* sb = [UIStoryboard storyboardWithName:#"mystoryboard"
bundle:nil];
UIViewController* vc = [sb instantiateViewControllerWithIdentifier:#"ExampleViewController"];
If it is still in its own xib file, then you don't change anything.
If you've moved everything into a storyboard, then you wouldn't often need to do this as you'd link between view controllers using segues.
If neither of the above are true, i.e. your view controller is on the storyboard but no segue connects to it, then you want UIStoryboard's instantiateViewControllerWithIdentifier: method described in the documentation. You have to set the identifier in the storyboard for this to work.
Related
I have a problem with calling one UIStoryboard from the second. My first Storyboard - Main, second - Management. When you click UIButton no action occurs. My source code:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Management" bundle:[NSBundle mainBundle]];
UIViewController *yourViewController = [storyboard instantiateViewControllerWithIdentifier:#"Management"];
[self.navigationController pushViewController:yourViewController animated:YES];
There are so many reasons may be here.
1. You might forgot to setup IBAction outlet to your UIButton
2. Storyboard names may not match you specify in your code
3. [storyboard instantiateViewControllerWithIdentifier:#"Management"]; are you sure you specified the same Storyboard ID for this controller?
4. In order to check all these suggestions it's enough just to set breakpoint on first line of your code and try to reproduce the situation.
Many wrong things can happen in that code.
First of all be sure that your action is well connected, put a breakpoint in your action to see if that is being called.
Second be sure that the storyboard name is correct, put a breakpoint after storyboard and check if it isn't nil (po storyboard in the debug console).
Second be sure that the "Management.storyboard" has a ViewController with the identifier "Management". So put a breakpoint after yourViewController to check if it is nil (po yourViewController in the debugger console).
Finally be sure that the view controller where you have the action is inside the navigation controller. So check if self.navigationController is nil (po self.navigationController in the debugger console after you stopped in the action's code)
Need replace old code by this.
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Management" bundle:[NSBundle mainBundle]];
UIViewController *yourViewController = [storyboard instantiateViewControllerWithIdentifier:#"ManagementIDS"];
[self presentViewController:yourViewController animated:YES completion:nil];
If you prefer doing it in interface builder than in code:
You can now create a storyboard reference in interface builder. That means you can link a storyboard from another storyboard. Target must be ios9.
https://developer.apple.com/library/prerelease/watchos/recipes/xcode_help-IB_storyboard/Chapters/AddSBReference.html#//apple_ref/doc/uid/TP40014225-CH49-SW1
check 19:00
https://developer.apple.com/videos/wwdc/2015/?id=407
We are working on splitting our main storyboard into smaller ones so that it makes source control merging easier. Any ideas on what the right approach is to load a new storyboard from a UITabBar?
Here's what we have so far in our custom subclassed UITabBarController:
UITabBarItem *cardsTabItem = [self.tabBar.items objectAtIndex:kTabBarIndexCards];
cardsTabItem.image = [[UIImage imageNamed:#"navCardsOff"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
cardsTabItem.selectedImage = [[UIImage imageNamed:#"navCardsOn"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
cardsTabItem.imageInsets = UIEdgeInsetsMake(-5, 0, 5, 0);
cardsTabItem.titlePositionAdjustment = UIOffsetMake(0, -5);
I've done the same thing before, but with a UITabBarController. In that case we had a storyboard for each of the tab buttons, even though one of the storyboards only had 1 view controller in it. I think wether you're using a UITabBarController or responding to the tab bar delegate the answer is the same. For each button clicked make the determination of which storyboard the view controller you want to load is in:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"leftButtonStoryboard" bundle:[NSBundle mainBundle]];
UIViewController *vc = [storyboard instantiateInitialViewController];
//or
UIStoryboard *otherVC = [storyboard instantiateViewControllerWithIdentifier:#"CameraViewController"];
Then you can present it, push it, or whatever.
In my case since I was using a UITabBarController this was all done during initialization of the controller for all the different buttons.
It will most likely come in handy to by default name all of the different view controller your using in your storyboard (the storyboard id), I usually name them after the viewController class so I don't have to remember what I called it.
I would also recommend that you avoid using the self.storyboard property when trying to instantiate another view controller because you might end up with a situation where a controller is shared between tabs. Being explicit with which storyboard you're loading a controller from can help with readability and avoidance of bugs.
Edit - a more concrete example:
What you need to do is set the viewControllers property of your UITabViewController, I do this in its init method. For example
- (id)initWithCoder:(NSCoder *)aDecoder {
if (self = [super initWithCoder:aDecoder]) {
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]];
UIViewController *one = [mainStoryboard instantiateViewControllerWithIdentifier:#"VC1"];
UIViewController *two = [mainStoryboard instantiateViewControllerWithIdentifier:#"VC2"];
self.viewControllers = #[one,two];
}
return self;
}
You can use this technique if your writing it in code itself or if you're using a storyboard. Beware that if you have other view controllers already hooked up via the storyboard you'll loose then unless you instantiate them there as well. You can also use the setViewControllers: animated: method as well.
The code for creating the custom tab bar items (the buttons at the bottom) should probably go within the individual view controllers and be assigned to its tabBarItem property. The UITabBarController will use that property to create the correctly styled button. If you don't provide the property you get the default buttons starting from 1.
How do you identify a UIStoryboard?
The class has methods which create and instantiate but I don't see an #property with something like name. E.g.
Getting a Storyboard Object
+ storyboardWithName:bundle:
Instantiating Storyboard View Controllers
– instantiateInitialViewController
– instantiateViewControllerWithIdentifier:
Any suggestions?
====
UPDATE
I was hoping for something like self.storyboard.name or [self.storyboard description], e.g.:
NSLog(#"This Storyboard is: %#", self.storyboard.name);
Perhaps it's not meant to be.
You can identify a storyboard by its name in the project navigator:
You can identify a view controller from a storyboard by setting its Storyboard ID in the identity inspector in interface builder:
Once you have these, then you can access them through your code:
UIStoryboard *iPhoneStoryboard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:nil];
ViewController *firstViewController = [iPhoneStoryboard instantiateViewControllerWithIdentifier:#"FirstViewController"];
I'm completely re-formulating this question having learned that I was originally off track but that having me no closer to solving the problem. With reference to this image...
I am wanting to either create or manipulate the segue (highlighted in yellow) in code such that the Master view is any one of a number of subclasses of MFMasterViewController (highlighted in red).
When doing this using Nibs I could create a Nib, SharedNib.xib & set the class as MFMasterViewController, then create my subclasses, say MFMasterViewControllerSubclassA, MFMasterViewControllerSubclassB etc. & then instantiate whichever subclass I wanted using...
MFMasterViewControllerSubclassA *controller = [[MFMasterViewControllerSubclassA alloc] initWithNibName:#"SharedNib" bundle:nil];
or...
MFMasterViewControllerSubclassB *controller = [[MFMasterViewControllerSubclassB alloc] initWithNibName:#"SharedNib" bundle:nil];
etc.
Any clues as to how I can get this right using storyboards?
In my case the reason for wanting to do this is that all my subclasses are the same tableview & data but sorted differently & having some difference in what's written to the detail text of the cels. I suspect that it is a not uncommon pattern.
Cheers & TIA,
Pedro :)
It's not a direct answer but this is how I would accomplish what you want based on your explanation of the reason.
Basically you need to separate the UITableViewDataSource (and maybe the delegate too) from the MFMasterViewController so when the segue is executed you can set the correct dataSource and delegate in the view controller.
So in the Navigation Controller you need to implement the prepareForSegue:sender: method. This is where you can customize the segue before it is executed:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// you can set the segue identifier using Interface Builder
// also it is a good thing to make sure which segue you're using
if (([segue identifier] isEqualToString:#"TheId"]) {
id<UITableViewDataSource> dataSource = [[TableViewDataSourceImplementationA alloc] init];
[[[segue destinationViewController] tableView] setDataSource:dataSource];
}
}
This way you can get the customization you want without the need to create subclasses of your view controller.
And if you have access to WWDC videos, check the session #407 Adopting Storyboards in Your App.
For anyone stumbling upon this question, you should also consider more generally using a "Strategy" pattern as an alternative to subclassing your controller. The accepted answer is a form of that, where the strategy implemented comes from whatever the data source/delegate is, and can be switched out at runtime. Another example of this is https://stackoverflow.com/a/17381927/954643
If your .m file is not associated with any storyboard, wouldn't self.storyboard be Nil?
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:
#"MainStoryboard" bundle:[NSBundle mainBundle]];
ViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:#"HauptMenu"];
Make sure to change the storyboardWithName: to whatever your storyboard is named.
NSString * storyBoardName;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
storyBoardName = #"MainStoryboard_iPad";
} else {
storyBoardName = #"MainStoryboard_iPhone";
}
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:
storyBoardName bundle:[NSBundle mainBundle]];
ViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:#"HauptMenu"];
I believe i finally found the answer. We want to use storyboard ViewController with another class name. There are many workarounds like using delegates but i think this is the best one. I already answered it in another topic. Hope it helps!
https://stackoverflow.com/a/32103618/1943053
I need to make a set of decisions in the AppDelegate on launch - depending on the outcome of those decisions I need to go to specific parts of the storyboard.
So my question is - WITHOUT using any nav or tab controllers, how do I go to a specific part of a storyboard?
OR
Is the only supported option having multiple storyboards - for each of the 'outcomes' and then loading those as required?
Thanks
Give each ViewController a unique identifier in the storyboard.
Then in the appDelegate:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"PUT_UNIQUE_ID_HERE"];
//DO WHAT YOU WANT WITH YOUR VIEWCONTROLLER
//Example:Set it as the root view of the app window...
Give each of your ViewControllers a separate ID, and then instantiate the required one with:
UIViewController *initialVC = [storyboard instantiateViewControllerWithIdentifier:#"<identifier>"];