How to merge two ios apps into one - ios

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];
}

Related

Navigate between multiple storyboards in iOS App

I wanted to have separate storyboard files for every UIViewcontrollers in my iOS app.
So how can we assign different storyboards for each controllers? Also how do we do navigation between those?
This I am doing to avoid svn conflicts while so many people working on UI.
get a reference to the storyboard...
UIStoryboard *someStoryboard = [UIStoryboard storyboardWithName:#"NameOfYourStoryboard" bundle:nil];
then instantiate either the initial viewcontroller from that storyboard...
UIViewController *initialViewController = [someStoryboard instantiateInitialViewController];
or some other viewcontroller identified by it's storyboard identifier...
UIViewController *someOtherViewControllerFromTheStoryboard = [someStoryboard instantiateViewControllerWithIdentifier:#"SomeViewControllersStoryboardIdentifier"];
after that you can simply push (within a navigation controller) or present the new viewcontroller.
since iOS 9.0 you can even connect storyboards via storyboard references in the storyboard itself:
https://developer.apple.com/library/prerelease/ios/recipes/xcode_help-IB_storyboard/Chapters/AddSBReference.html
Keeping different storyboards for different modules is good approach. You can achieve the navigation between storyboards as follows:-
Suppose you are in A view controller and want to push another view controller named FabIdeaDetailViewController which is present in storyboard named FabIdeas:-
FabIdeaDetailViewController *horizontalListController = (FabIdeaDetailViewController*)[UIViewController instantiateViewControllerWithIdentifier:#"FabIdeaDetailViewController" fromStoryboard:#"FabIdeas"];
[self.navigationController pushViewController:horizontalListController animated:YES];
Now for pushing another view controller named WishlistViewController which is present in storyboard named Wishlist:-
UIViewController *WishlistViewController = [UIViewController instantiateViewControllerWithIdentifier:#"WishlistViewController" fromStoryboard:#"Wishlist"];
[self.navigationController pushViewController:WishlistViewController animated:YES];

Loading a storyboard from a different Xcode project

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.)

iOS iPad storyboard is not being selected

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];
}

iOS Change Story Board

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.

How to use tabbar in mac Application

i am trying to develop mac application(cocoa app).i have successfully used tabbar in iphone app. but in developing mac application ,how to use tabbar?
As we use tabbar for iphone application,i want to implement same kind of functionality for Mac App(cocoa app).
any idea?how its possible?
I presume you are talking about an NSTabView when you refer to "tabbar" or "Tababr"...
You do not need to write your whole app in one AppDelegate.
You can add your AppDelegate as a delegate of your NSTabView and then implement tabView:didSelectTabViewItem:. This allows you to intercept requests by the user for different tabs. Just create an outlet for your tab view and set the delegate:
[[self tabView] setDelegate: self]
Based on the requested tab you can then create the view controller associated with that tab and load the NSView into the selected tab. Something like:
- (void)tabView:(NSTabView *)tabView didSelectTabViewItem:(NSTabViewItem *)tabViewItem {
MyViewController aController = [[MyViewController alloc]
initWithNibName: #"MyView" bundle: [NSBundle mainBundle]];
[tabviewItem setView: [aController view]];
}
I'm not sure whether you need to add NSTabViewDelegate as a protocol to your AppDelegate but if Xcode flags a warning you'll notice:
#interface MyAppDelegate : NSApplicationDelegate <NSTabViewDelegate>
Hope this helps. Otherwise you need to elaborate on your requirements.

Resources