Completely unload a ViewController at modalTransition? - objective-c

normally after a modal transition, the second viewController runs further "behind" the visible ViewController in the background.
Is there a possibility to completely unload the second ViewController ??
If don't want to use push, because I want an animation on the transition...

Several points:
You are worrying about something that is not a worry. View controllers are lightweight, simple objects. The only heavyweight object is the view, and it is in fact removed from the interface when another view controller's view is presented in its place.
The game does not "run in the background". If it does, you're doing it wrong. You should be detecting in viewDidDisappear: that your view is no longer in the interface and stopping all the activity. That's what these sorts of events are for.
If you're still bent on making certain the view controller itself is destroyed when the game is not showing, then use a different architecture. For example, present the game controller. When the game controller is dismissed, it will be released and destroyed.

Related

Custom segue that 'finishes' early?

I'm looking to implement a custom segue that pushes to a UIViewController, but completes before the new UIViewController fully fills the screen, leaving some of the source view controller still in view and functional. (For example; new view controller covers half of the user interface).
I'm keen to use a segue rather than a view that is moved using CGRect, Quartz framework method, or similar, as constraints get messy really easily, unless a custom segue could utilise such methods(?)
Any pointers greatly welcomed! :)
For this task you would use a container view controller, which manages and displays the content of multiple other view controllers at a time while letting them interact with their views like normal. An example of this would be the UISplitViewController, which displays two view controllers' views at a time, one on each side of the screen. You can design segues that swap out one view controller of the multiple on display in a container view controller, similarly to the Replace Segue implemented by Apple to swap out a UISplitViewController's detail view controller (the one on the right hand side).

Two view controllers (with nibs) acting on the screen at the same time

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

Putting an ADBannerView on top of a UINavigationController

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

Are modal view controllers the preferred way to replace the entire interface on an iPad?

Specifically, I have something like a game, with a menu screen made out of standard components. I want a button to switch to another view controller that the user will interact with for a while, then return to the menu screen. It seems like having the menu controller present the 'game' mode as a modal view controller is the most straightforward solution, but is this the best way to essentially replace the entire view? Is the whole menu (which may later become a deep nav or split controller) kept in memory as long as the modal controller is in front, and is this something I should bother to worry about?
There are really two parts to this question:
Which method of transitioning from one view to the next in an iPad application provides the best experience to the user?
Which method of transitioning from one view to the next is easiest to implement and best handles memory management?
I'm not going to try to address the first part of this question other than to point you to Apple's 'iPad Human Interface Guidelines' which says (among other things):
Reduce Full-Screen Transitions
Closely associate visual transitions with the content that’s changing. Instead of swapping in a whole new screen when some embedded information changes, try to update only the areas of the user interface that need it. As a general rule, prefer transitioning individual views and objects, not the screen. In most cases, flipping the entire screen is not recommended.
When you perform fewer full-screen transitions, your application has greater visual stability, which helps people keep track of where they are in their task. You can use UI elements such as split view and popover to lessen the need for full-screen transitions.
http://developer.apple.com/library/ios/prerelease/#documentation/General/Conceptual/iPadHIG/DesignGuidelines/DesignGuidelines.html
However, in your case I'd have thought a full-screen transition is entirely appropriate (but then I'm not a user experience expert).
In answer to the second part, yes displaying a new view controller modally seems like a good approach to take.
By default both the objects used by the menu view and those used by the modal view will be kept in memory - but the great thing about using UIViewController sub-classes is that they've got some default memory management built-in. If your application receives a memory warning whilst the modal view is being presented in full-screen mode, the menu view controller's views will be removed and it's 'viewDidUnload' method will be called. So in your implementation of this method you should release any objects you don't need and then recreate them as needed in the menu view controller's viewDidLoad method (which will be called again before the menu view is shown).
This is explained in more detail in the UIViewController class reference:
When a low-memory warning occurs, the UIViewController class purges its views if it knows it can reload or recreate them again later. If this happens, it also calls the viewDidUnload method to give your code a chance to relinquish ownership of any objects that are associated with your view hierarchy, including objects loaded with the nib file, objects created in your viewDidLoad method, and objects created lazily at runtime and added to the view hierarchy. Typically, if your view controller contains outlets (properties or raw variables that contain the IBOutlet keyword), you should use the viewDidUnload method to relinquish ownership of those outlets or any other view-related data that you no longer need.
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIViewController_Class/Reference/Reference.html

Strategy for two mutually exclusive UIViews

I have been doing spring cleaning in my app. I noticed something strange, that, when I tried to correct it, completely crashes my app.
There are two "paths" in my app; either you are in the "A" part of it or you are in the "B" part. From the "A" part you can go to the "B" part and the other way around.
I designed it so that the app delegate class has two methods; switchToAView and switchToBView
So being in the middle of the BView and calling the switchToAView method on the app delegate should completely release everything related to the BView and send the user to the AView.
I found out when switching to the AView the BView view was still retained.
Each view is held by a property.
interface;
#property(nonatomic, retain) UIView *viewA
#property(nonatomic, retain) UIView *viewB
implementation;
#synthesize viewA, viewB
in the appDelegate.
I put a breakpoint in the dealloc method of the two views. (viewA and viewB).
Now this happens;
When loading up viewA and from there switching to viewB, nothing is released(as expected). Then when I switch from viewB to viewA, viewA is first released (by the generated setter, as far as I can figure out).
and then viewA is initialized and displayed.
This works just fine but has the downside that both viewA and viewB is alive on the stack at the same time :/ this is not desirable as they are mutually exclusive. The viewA is only released when a new viewA comes along, however, viewA should be released when a viewB is added to the window
I then tried releasing the viewA in the switchToBView method.
This works fine when going from viewA to viewB. I checked with instruments and the retain count drops to 0 for the viewA. Now when switching back to the viewA, the app crashes, and I think it is because the:
self.viewA = newlyInstantiatedViewA;
setter, first sends a release message to the viewA, but I released viewA earlier, and this causes the crash.
I can't get my head around that using a setter this way, will cause a crash. ("message sent to deallocated instance" and breaking in the dealloc method of the last subview added to A when [super dealloc] is called)
Should I have chosen a different approach all together?
And how will I build something sturdy, that ensures only one view is kept alive at a time?
Sorry for the lengthy writing, I would have written less if I had more time:
Thanks you in advance for any solution or design suggestions:)
Should I have chosen a different
approach all together?
Quite definitely, you mixed view controller logic into your views and you have views mutually retaining each other in what appears to be a circular reference.
(1) The views should not have logic for loading other view. Loading and unloading views is the function of the view controller. A view should only be concerned with logic immediately relating to the display. It should not even store or manipulate any user data.
(2) View controllers should seldom call other view controllers. The view controller should be concerned with managing the view and reading and writing data from the view to the data modal.
(3) If you need to relate views, use a UINavigation controller. It's not just for strictly visually hierarchal view patterns. Plus you can hide the nav bar so the user never sees it. You need to have a view controller that pushes viewA and when you need viewB, call the nav to pop viewA and push viewB. To the user, it will look like the views are simply swapping our. See the utility flip view for a similar use.
Your app works temporarily because there is nothing in the language or API that prevents you from cramming almost the entire application logic into a view subclass. However, keeping such a design running and reliable is nearly impossible.