I have two different but related projects. Parent project A has a storyboard. Child project B, which (in theory) extends the functionality of A, needs to instantiate A's main storyboard in its AppDelegate. In my xcode workspace, I've included parent A within child project B, as a linked project and I can see all the files. I am using the following code in application:didFinishLaunchingWithOptions:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"iPhone.storyboard" bundle:[NSBundle mainBundle]];
MainViewController *vc = (MainViewController *)[storyboard instantiateInitialViewController];
_window.rootViewController = vc;
[self.window makeKeyAndVisible];
The code fails at runtime at the storyboardWithName line, I assume because iPhone.storyboard is not available immediately within B, and it doesn't know to look for it within A. The actual storyboard file is located in a different folder outside child project B's project folder on disk.
It has nothing to do with B and A. Files in the project can be located anywhere. Your error is at runtime. It has to do with the app you are building and running. Think about what this line says:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"iPhone.storyboard" bundle:[NSBundle mainBundle]];
So you are claiming here that there is a storyboard called iPhone.storyboard inside this app's main bundle. But there isn't. The app is building and you aren't doing anything to cause the storyboard to be copied into the app's bundle as part of that process. That's what you need to do.
To get the storyboard to be in the main bundle, add it to this app's Copy Bundle Resources build phase.
(Now, of course, there may be other problems, e.g. if classes referred to in this storyboard are not also part of this app. But that's not what your question was.)
Related
I created a workspace and added two projects in Xcode workspace. One new and one existing. I want to access a storyboard of an existing project within a tap of a button in new project. Can I do that?
Existing project is linked with a lot of libraries and one of them is Tapku library. It works fine, but I want to have a new project and some buttons there, that when I tap a button I access an existing projects storyboard and then work with that so called application.
thank you.
This is what I tried to do:
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Main_iPad" bundle:nil];
UIViewController *vc = [sb instantiateViewControllerWithIdentifier:#"LoginView"];
vc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:vc animated:YES completion:NULL];
and I have error:
Could not find a storyboard named 'Main_iPad' in bundle NSBundle "somePath/Application1.app (loaded)
This storyboard is in Application2 Project.
I have two ios app one variant of the app is for the teachers and second version is for the students.Student version is live from the last two year on the app store.This version is non-ARC project .Now developed the teacher variant of the app .this version is using the storyboard and have the ARC.
My problem is that in the student version application is tabbar based and tabbar is declared in the app delegate .where as in the teacher version the application is based on heavily customised uinavigation controller like the side slide in menu ;which is declared in app delegate too.Now my problem is how can i combine these two project into one iPhone app.
Both teacher and students can be identify based upon the login.
I would try to re-work the student version into a storyboard (a separate one from the teachers version) and update it to ARC. Then, base on the login results (student or teacher), load the appropriate storyboard. So after you have the results of the login, you could do something like this:
UIStoryboard *storyBoard;
if (isStudent) {
storyBoard = [UIStoryboard storyboardWithName:#"MainStoryboard_student" bundle:nil];
}
else {
NSLog(#"teacher!");
storyBoard = [UIStoryboard storyboardWithName:#"MainStoryboard_teacher" bundle:nil];
}
UIViewController *initViewController = [storyBoard instantiateInitialViewController];
[self.window setRootViewController:initViewController];
In order to make sure your app will replace the one in the store, make sure you keep the same bundle ID for the new combined app as you had for the student version currently in the store.
If you do not want to convert the student version files to ARC, you can convert the project to ARC, but flag the student classes that have not been converted to arc with the -fno-objc-arc flag
Basically, click on the project file, select your target, select the Build Phases tab, and for each of the old project files that do not use ARC, add -fno-objc-arc in the Compiler Flags field in the Compile Sources section.
If both teachers and students can be identified at the login stage, to solve this problem you most likely would need create a unified login page (root view controller) in your AppDelegate. Then after the user logins you determine what part of app would be more appropriate and show the next view controller embedded in UINavigationController or UITabBarController.
you can can make student project compatible to ARC by adding compiler flag -fno-objc-arc to all class files of student project.
remove auto loading of storyboard from the project settings, in AppDelegate define the logic for loading the rootview.
if (isStudent) {
UIViewController *rootViewController = [[UIViewController alloc] init];//whatever you appdelegate code for student is
[self.window setRootViewController:rootViewController];
}
else {
NSLog(#"teacher!");
UIStoryboard *storyBoard;
storyBoard = [UIStoryboard storyboardWithName:#"MainStoryboard_teacher" bundle:nil];
UIViewController *initViewController = [storyBoard instantiateInitialViewController];
[self.window setRootViewController:initViewController];
}
I am new to iOS, started working on static libraries.
I have a main project and a static library project. I have added my library projects header and lib.a in the main project. I am able to call library project's methods from main project. But library project has a storyboard named: LibStory.storyboard while main project has storyboard: MainStory.storyboard.
When I start my app view starts from MainStory.storyboard then I have to call my library project and start LibStory.storyboard. When I start storyboard of lib project, I get this error:
Warning: Attempt to present on whose view is not in the window hierarchy!
LibStoryBViewController is in lib project. Do I need to add "LibStory.storyboard" in main project, I did that too still not working.
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"LibStory" bundle:nil];
UIViewController *vc = [sb instantiateViewControllerWithIdentifier:#"te"];
vc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:vc animated:YES completion:NULL];
This is the code in lib project to call storyboard. Please suggest me how to solve this?
It seems that Xcode 5 is not choosing to use my iPad storyboard for the iPad device even though i specified it.
This is how i told Xcode 5 to use iPad storyboard:
I went to project settings under General
Selected Devices: Universal
Then i clicked on iPad
And wrote MainStoryboard-iPad.storyboard in Main Interface
But for some reason even though i make changes to my MainStoryboard-iPad storyboard its not being showed when i try to run it on an iPad.
I only have two storyboards in my project
MainStoryboard-iPad.storyboard
and
MainStoryboard.storyboard
Any ideas what could be wrong here?
Oh by the way, when i selected Universal the first time i got a box asking me something about copying (i never read it that carefully). I just hit Yes. Not sure what that box actually did.
EDIT
Code that runs in my AppDelegate.m
- (void)applicationDidBecomeActive:(UIApplication *)application {
AppDelegate *app = [[UIApplication sharedApplication] delegate];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController *ivc = [storyboard instantiateViewControllerWithIdentifier:#"mainStoryBoard"];
UINavigationController *nvc = (UINavigationController*)self.window.rootViewController;
app.window.rootViewController = ivc;
}
I just encountered this a while ago.
These are the steps you need to do:
make sure the "Deployment Info" -> Devices is "Universal"
Create a storyboard for iPad (e.g) MainStoryboard_iPad.storyboard
now go to your Infor.plist
add row for "Main storyboard file base name (iPad)" and use MainStoryboard_iPad as the value of the string
Now you are good to go!
Your code is overriding the default storyboard for the device type. You are grabbing MainStoryboard, instantiating a view controller from it and setting it as the root. This is normally handled by the storyboard itself. It uses the view controller that you have picked as the root. Try removing all of that code to manually set the storyboard.
Check this project on github for an example of storyboard switching without code: https://github.com/danielmackenzie/StoryboardSelection
Xcode project points to each storyboard per device type and the appropriate board is automatically chosen on launch.
You'll need an entry for the iPad in your app's info.plist
Look in your Supporting Files group for the info.plist for your app.
You'll see an entry for the iPhone's storyboard, but not one for the iPad.
The iPhone entry should look like this:
Main storyboard file base name
and it should have the name of your iPhone's storyboard (sans file extension) as the string value for it. Something like this:
iPhone-Storyboard
Add a new entry into the pList and enter this string as the key:
Main storyboard file base name (iPad)
Make sure the data type is string.
You can now select the iPad storyboard that you want from the app's General Settings on your Target.
I JUST ran into this as well and thought you'd like a clear explanation and solution.
Sometimes, Xcode is rather maddening, isn't it? Hope this helps.
// Override point for customization after application launch.
if (<your implementation>) {
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main"
bundle: nil];
YourViewController *yourController = (YourViewController *)[mainStoryboard
instantiateViewControllerWithIdentifier:#"YourViewControllerID"];
self.window.rootViewController = yourController;
}
return YES;
Your logic is not taking into account your device. AFAIK, there is no method that looks at your naming postfix ("-iPad") and automatically selects the right storyboard file.
To fix it, simply replace the call to instantiate your storyboard with some logic to pick the right one based on device.
UIStoryboard* storyboard;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard-iPad" bundle:nil];
} else
{
storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
}
My iPad App has two storyBoards - FirstStoryBoard and SecondStoryBoard
I have a single ViewController
I notice that Under Project > Targets > Summary there is an option for specifying the MainStoryBoard and if I change this setting the correct story board loads correctly.
The Question - How can I change the behavior so that I can change between the first and second story board at run time. In other words I want to
First, create storyboard instance:
UIStoryboard *board = [UIStoryboard storyboardWithName:#"MyStoryboard" bundle:nil];
and then get first view controller from it:
UIViewController *vc = [board instantiateInitialViewController];
add as child view controller:
[self addChildViewController:vc];
or maybe (if you are in AppDelegate.m / application:didFinishLaunchingWithOptions: method)
self.window.rootViewController = vc;
The Question - How can I change the behavior so that I can change
between the first and second story board at run time.
You can't switch the value of the Main Storyboard setting (specified by the UIMainStoryBoard key in your Info.plist) at runtime, so do the next best thing: use a common storyboard or nib file that contains very little, and then instantiate the storyboard that you want using the UIStoryboard class. For example, you could use a simple nib file to create your app delegate, and have the app delegate's -application:willFinishLaunchingWithOptions: load first view controller from the storyboard of your choice.