I have been learning iOS development for a few days now. At this moment, I have questions over how the rootViewController is to be used. I searched the web for 3 hours yesterday looking for the answer which turned up quite a few results that never really answered my question.
I am trying to learn to program an app using code only (no storyboards/xib files). I currently am trying to understand how to properly switch between views without using the UINavigationController. In my project I have the main delegate which creates the window, initializes my main view controller (which loads the separate view as well) and adds it as the rootViewController.
My first view has a button which calls a function in its controller to switch to my next view. Here is where my question arises: Do I switch the main rootViewController to the next view or do I load the next view as a subview of the rootViewController? Is the rootViewController supposed to encase all the views for an application? (I think this is how the UINavigationController works)
I have gotten switching of the rootViewController to work in my app, but I want to make sure there isn't some other way I am suppose to manage my views.
I would not switch the rootViewController, I think that should remain stable. So you could add it as a subview, or you can present it as a modal view.
And of course, you can just change the rootViewController to point to your new view if that's how you want to do it.
Related
Just as a disclaimer, I am an iOS beginner, in a pretty unique position. I'm an intern learning on the job, with a hard deadline for a test app, with specific specs. So I unfortunately don't have the luxury of learning all that I should about xCode and objective C.
Anyways, I am trying to create a navigation menu similar to the iPad's slide out menu. I've looked at plenty of sample code given in response to questions like this in the past. It all works perfectly fine, but I can't understand all of what they're doing. I think this results from being fairly bewildered by view controllers and delegates. And, since I'm supposed to be writing this all by myself, I can't just build off of their existing code.
My plan for this working is to have one main view controller, containing the navigation menu in a table view. This is hidden behind a normal UIView, until a button is pressed, at which point the normal UIView slides offscreen enough to reveal the menu. Upon selection of a menu item, the normal UIView would slide back to its original position, and be replaced by the relevant UIView, controlled by its view controller. In other words, clicking on the menu item relating to "Home" would load the homeViewController.xib, controlled by the homeViewController. This would be loaded in that normal UIView subview, on top of the tableView.
I'm able to load a view in that normal UIView as a result of a button press.
homeViewController *_homeViewController = [[homeViewController alloc]initWithNibName:#"homeViewController"];
[self frontView] = _homeViewController.view;
There may be some syntax errors in that code, since its from memory. I'm not able to access the computer with my code on it at the moment, but that's the general gist. Basically, that places the home view nib on the frontView (that normal UIView that's over the table view), but its not connected to homeViewController. Or at least I think that's the issue, when I press a button, that's correctly connected between the nib and the homeViewController.h, and only set to NSLog in the .m file, the application crashes.
Any idea how to connect this nib to its viewController when displayed in this way? Or, to create the nib in IB, without the associated .h and .m files, and use the main view controller as the homeViewController as well? Or, if my logic is inherently flawed, what SHOULD I do? Something with NavigationControllers?
EDIT:
I also tried a new approach- changing homeViewController's file owner to viewController, and connecting the button on homeViewController's action to viewController. This too caused a crash upon pressing the button. I really think the issue is with having multiple view controllers acting on screen at once, or having multiple views from separate nibs, controlled by one view controller on screen at once.
I suspect that your immediate problem is that _homeViewController is being freed as soon as you leave whatever method that code is in. To fix this, create a strong property in this class that holds the _homeViewController for as long as its view is needed and allocate it to that property rather than a local variable. That way, buttons (or whatever) that are part of that view still have a valid controller object backing them.
In the long run, pushing or presenting view controllers when you need the screen to change is a much better strategy but, as I said, the immediate problem.... :)
I have a very very old iPhone/iPad app, actually it was my very first Objective-C app, I started learning iOS programming on it. Now I want to update it a bit but have following problem:
The app has never had any viewController. When I started writing it, I wasn't familiar with MCV and Interface Builder. First version was just for iPhone and it made the UI manually by just positioning UILabels and UIButtons in UIApplicationDelegate's didFinishLaunchingWithOptions via addSubview directly into self.window (there is MainWindow.xib but it's empty). A couple of months later I created iPad version. It has all the UI created in Interface Builder in a single MainWindow_iPad.xib. There are no other xibs, just UILables and UIButtons placed directly in MainWindow_iPad.xib and no view controller was used again.
Now, a couple of years later, I want to update this veteran app a bit. I want to add a root view controller so I set window.rootViewController in UIApplicationDelegate's didFinishLaunchingWithOptions. I have no problem with the iPhone version, it works a treat. But I have troubles with the iPad one. After setting window.rootViewController, the app doesn't interact to any touch at all. It loads, the UI is created but it's just frozen.
Any idea what could be wrong? Thanks a lot!
Don't tell me I should throw it away and write it again from scratch in a normal "experienced way", I know this would be the best way but I don't need to update it that much to waste so much time.
Relevant Data:
I'm making a simple game, using OpenglES. The game itself is done, however I would like to have a main menu as well as some other screens designed in IB. So far I have a death/score screen that is displayed with a simple modelviewcontroller.
I haven't done a ton with GUI building or much programming on the platform outside of C code (posix sockets) and some examples from some books. So I'm not sure how I would go about having lots of views- usually I just use a model view, and it's gotten me along just fine so far. However I don't think that would be the best route here.
Situation:
I have a view controller that shows my main menu- the main menu branches off to the main game, a settings screen, and a high score screen. The main game is made in opengl, and I haven't made the settings view yet, but it likely will be as well. How should I switch between the views? Presenting the main view from the app delegate is as simple as setting the root view controller = newly created view controller, should I do the same thing here? If I do that can I remove the resources from the menu view controller?
Sorry if this is an extremely simple question, I just don't quite get the process.
I'm not entirely sure what you want to do, but an easy way to show a new view controller is:
SecondViewController *aSecondViewController = [[SecondViewController alloc]
initWithNibName:#"SecondView" bundle:nil];
[self presentModalViewController:aSecondViewController animated:YES];
I hope that helps.
How should I switch between the views?
In the vast majority of cases, you should be using a UINavigationController. Your initial controller would be the main menu. When you want to go into a particular section of your application, you push a new view controller onto the stack. When you want to come back out, you pop it off the stack.
Besides navigation and presenting modally that others have mentioned, another option is to swap out views. May or may not fit your app's flow but wanted to point out another option for you to consider
Best practice for switching iPhone views?
If you are already limiting the game to iOS 5 for some other reason you should look into UIStoryboard. If you don't currently require iOS5 the "simplest" way is to use table views, but that isn't a very "gamey" UI.
I'm trying to put an iAd banner in an app that is based on a UINavigationController (it's not the standard nav-base app proposed by xcode, cause I don't need the table view).
I'd like to place an ADBanner on its bottom, to be always visible, no matter how the user pops and pushes views.
I studied the iAdSuite example in the apple sample code, but, though it's reported among the "best practices", I don't think it's the best practice for what I need. It basically declares an ADBannerView in the app delegate class and then implements the ADBannerViewDelegate methods for every single view the app needs. That means implementing the ADBannerViewDelegate methods over and over again on every view controller class you need! It doesn't seem too smart... :(
I'd rather prefer to have an approach more similar to what Apple itself does in the tab bar based app, where you have a part of the window always occupied by the tab controller and all the views switching above without affecting the tab bar view below.
You can't directly put an ADBannerView along with the nav controller in the app delegate, because ADBanner needs to be placed in a view controller (you get a runtime error otherwise).
I tried to subclass from UIViewController, implementing the ADBannerViewDelegate in this class, and place it in the rootViewController along with a UINavigationController but I'm not having good luck with this approach...
Has anybody found a good, simple way to to this? Any hint?
Thank you for any help...
You can have just one class for ADBannerViewDelegate, and just one instance of ADBanner itself. When the currently active view changes, remove ADBanner from the old view, add it as a subview to the new view.
EDIT:
to clarify, you don't need each view implement the ADBannerViewDelegate. You only should have one class implement it (that class doesn't have to be a view controller for that matter).
You would also need to maintain a somewhere a property that would point to the currently active view (e.g. you can update that property in your Navigation Controller's navigationController:didShowViewController:animated:, or come up with your own protocol for that if your views appear in a more complex way).
Then in your ADBannerViewDelegate you'd just resize the view currently pointed to by that current view property. The actual view doesn't even have to know it has an ad in it ;)
I'm creating an iPad app based on a UINavigationController (with the bar hidden) so I can push and pop other viewControllers for navigation around the app. However, I am now wanting to add a section in which there are two viewControllers that I want to be able to switch between, so in other words they are side-by-side, rather than hierarchical.
Is it okay to use a UITabBarController for this? I am aware that on the iPhone it is recommended they are used only at the root level of the app, but since this is an iPad app I wondered if I could use it? Also, I guess I need to create an empty viewController, create a UITabBarController within it and set the delegate to it, then add the two viewControllers to it... So in effect I will have a viewController within another viewController, and when I have done that in the past the results have been very flaky.
Can I do it this way? The only other way I can think of doing it is to have two plan UIViews within a UIViewController, but that also means I shouldn't really put any business logic in them (bad MVC!), and not being able to will be a right pain in the a**.
Any ideas?
Thanks!
:-Joe
EDIT: I also need to be able to swipe-animate between the two VCs within the TabBarController, AND have a menubar over the top which doesn't animate... Can I do this?
Sure.
I do this kind of thing all over the place in an app I'm working on. I actually have several different types of "toolbars" that can be optionally shown at different times.
What I do is create a "parent" member in my toolbar's class - and when a button is pressed, I have the toolbar call a method in the parent class to do whatever needs to be done - (i.e. display another view).
This avoids the whole mess of creating a view inside another view (or viewcontroller inside another viewcontroller - or whatever) - the toolbar can take the button hits, but all the views are opened by the root view/controller.
Hope this helps/makes sense!