When I run my app on the simulator, then I go Hardware->Simulate Memory Warning it causes my view to go blank (I just see white). Does anyone know how I can make it NOT do that? -- I don't want an actual memory warning to make my screen blank.
Thanks
I'm having the same issue. I have an application where you're presented a login screen, which pushes under a NavController a main menu. Every selection in the main menu then pushes a new view controller. If i get a memory warning when under a menu item, going back to the menu displays a blank view.
This is probably more of masking the symptom than fixing the problem, but by overriding my main menu's didReceiveMemoryWarning message with an empty one (so that the super version isn't being called) stopped the view from disappearing.
I like this better than overriding setView (as recommeneded here) because you don't get the pesky performance warning about "-viewDidUnload caused the view to be reloaded."
I got the same issue right now and I solved the problem.
In my case I got this lines inside the mainViewController's code:
- (void)loadView {
[super loadView];
}
after simulating a memory warning the system call didReceiveMemoryWarning and you can check that viewDidUnload is called immediately after and if you use loadView inside your code the class call it to reload a brand new page that replace your old view.
This cause a blank screen.
So to solve the issue I just commented the three line above.
bah, it was mainly because I set my navigation controller incorrectly
Related
I'm getting strange navigation bar behaviour, for example when I hit back button the screen displayed is the previous screen, however the Navigation Bar items do change. So I'm left with screen A, but with nav bar buttons for screen B.
Could this be due to memory leaks? I do note with my app still:
This behavior seems to happen:
immediately if I trigger memory
warning via the simulator menu, or
on a device after it has been on
for a while [without being killed
and then restarted as an app].
I do have some memory leaks I'm
trying to clean up (i.e. Profiler
highlights items in "leaked blocks"
section)
Any tips on fault finding root cause of why pushing a back button would end up in a weird state? e.g. screen on previous parent view, but nav bar items don't change...
UPDATE - I have finally removed the memory leaks in my app, however I note the nav bar issue still remains. I guess this doesn't confirm the answer to my question is NO in general, but in my specific case it wasn't the memork leak...
From Apple:
The navigation controller updates the
navigation bar each time the top view
controller changes. Thus, these
changes occur each time a view
controller is pushed onto the stack or
popped from it. When you animate a
push or pop operation, the navigation
controller similarly animates the
change in navigation bar content.
Based on this, I would start by looking for a bug or misconfiguration in your view definitions. Check for any InterfaceBuilder warnings if you defined your views via NIBs. Make sure your view hierarchies are correct in both UIViewControllers. Also check for possible bugs in your view life-cycle methods: viewWillAppear:, viewWillDisappear:, etc,.
Actually, it would be nice if you could post some screenshots and/or code. Thanks!
Any view that is not currently visible and only retained by it's view controller (as a part of the view property of that view controller) will be released (along with any non retained subviews) when a memory warning occurs.
Chances are you are creating the view as a part of init, and not retaining it in the controller (simply letting the view socket hold it from releasing). One way around this is to create properties for the views you create (nonatomic, retain), and after creating them and autoreleasing, assign to those properties, don't forget to assign those properties to nil as a part of dealloc to avoid leaking. Another way is to create your custom view elements in viewDidLoad as opposed to init.
Hard to say without code example from the offending views :)
I've seen something like this happen after calling -[UINavigationController setViewControllers:]. You might try not doing any programatic manipulation of the navigation controller's view controller beyond calling -[UINavigationController pushViewController:animated:].
I have a tab bar application and i am encountering a strange behaviour....when i toggle the tab bar and reaches into new view controllers sometimes the viewDidLoad of these view controllers are getting called...though viewDidLoad should get called only first time...
can anyone tell...any suggestion??
If there's a low memory warning then a tab bar controller will release all views that are not visible. This means that you can get viewDidLoad called more than once because the view has been unloaded.
Is your app memory-intensive, perhaps to the point that you're receiving memory warning? Though I have not experienced the behavior you're describing, it's possible that due to heavy memory use your unseen views are being released due to a lack of memory. When they're next called into view they would need to be reinitialized, calling viewDidLoad.
Are you sure it's viewDidLoad, not viewWillAppear?
viewDidLoad will only be called once in each UIViewController subclass, so if your layout is like this:
-UITabBarController:
- HappyUIViewController
- SadUIViewController
- ThirdUIViewController
Then viewDidLoad will be called three times. Once for HappyUIViewController, once for SadUiViewController, and so on.
So, my app is a set of stacked views, with a RootViewController as the 2nd view on the stack. The bottom-most view is a menu page, which loads either the rootview controller or an info view onto the stack, and from the rootview controller theres several more views.
When I receive a low memory warning, my app does fine unless I try to pop to the menu page from the rootviewcontroller or the info page. If I want to go from anywhere else within the rootviewcontroller to another view, it is fine until I try to unload the rootviewcontroller by popping it off the stack. Without a memory warning, the rootview will pop to the menu just fine. But if I simulate a lowmemory warning and try to pop the view, then it crashes. Once again, only a crash on both a lowmemory warning and popping a controller to get to the menu page. I have no clue whats going on, I cant find any memory leaks, nothing being over-released.
This is my first app so maybe I'm missing something obvious.
So I commented out the [super didReceiveMemoryWarning] on the Menu page, and it is working! I guess it was unloading the view each time. Everythings working fine. There was nothing to release on that page anyways so it shouldnt be an issue. Putting this answer here for other ppl who may have the same problem later on
I'm doing an iPad tech demo and I'm running into a serious technical problem.
I have an app concept that leverages UISplitViewController, but NOT as the primary controller for the entire app.
The app flow could be described roughly as this:
Home screen (UIViewController)
List->Detail "Catalog" (UISplitViewController)
Super Detail Screen (UIViewController but could conceivable also be a child of SplitView).
The problem is in the flow between Home and Catalog. Once a UISplitViewController view is added to the UIWindow, it starts to throw hissy fits.
The problem can be summarized at this:
When a UISplitView generates a popover view, it appears to then be latched to its parent view. Upon removing the UISplitView from the UIWindow subviews, you will get a CoreGraphics exception and the view will fail to be removed.
When adding other views (presumably in this case, the home screen to which you are returning), they do not autorotate, instead, the UISplitView, which has failed to be removed due to a CG exception, continues to respond to the rotation instead, causing horrible rendering bugs that can't be just "dealt with". At this point, adding any views, even re-adding the SplitView, causes a cascade of render bugs.
I then tried simply to leave the SplitView ever present as the "bottom" view, and keeping adding and removing the Home Screen from on top of it, but this fails as SplitView dominates the Orientation change calls, and Home Screen will not rotate, even if you call [homeScreen becomeFirstResponder]
You can't put SplitView into a hierarchy like UINavigationController, you will get an outright runtime error, so that option is off the table. Modals just look bad and are discourages anyway.
My presumption at this moment is that the only proper way to deal with this problem is so somehow "disarm" UISplitViewController so that it can be removed from its parent view without throwing an unhandled exception, but I have no idea how.
If you want to see an app that does exactly what I need to do, check out GILT Groupe in the iPad app store. They pulled it off, but they seem to have programmed an entire custom view transition set.
Help would be greatly appreciated.
Apple states:
The split view controller’s view
should always be installed as the root
view of your application window. You
should never present a split view
inside of a navigation or tab bar
interface.
This does mean it should be root view and not subview of another view. Even though they add:
You should never present a split view inside of a navigation or tab bar interface
That does not mean you can add it as a subview of any other controller either. (sorry)
I have a feeling that what you are experiencing is the byproduct of trying to do so. I am actually surprised that GILT Groupe's app did not get rejected. Apple has a tendency to enforce these HIG guidelines rather strictly lately. They (as you found out already) cause a rather nasty runtime error when you attempt to add them to a NavigationController.
I've solved this for myself... actually worked around... by presenting all other possible full screen views as modals of the SplitView...
This is an unsavory way of doing things in my book, but Apple leaves you little choice if you want to leverage a SplitView only "sometimes" within an app.
I had some success by creating a second UIWindow. I associate the UISplitViewController with that, and switch it out with the main window when I want to show the splitview. It seems to work they way I wanted, except for a slight delay in rotations and a log message about "wait_fences".
Unless your developing for jail-broken devices then bending apples rules/wishes isn't a good idea. Like Jann and Jasconius state above this means keeping a splitView controller view root, not over-using modals (vague) and not using multiple windows.
Also, the Gilt app is only available in the US
I'v been trying to find a solution too and have ended up programatically removing views from the window like Tuannd talks about but the landscape rendering bug is unforgivable.
#Jasconius, What is the max number of modals are you are presenting at any time?
I am struggling with this same issue. I've been trying various things poking at the UISplitViewController as a black box and see how it reacts.
I seem to have come up with a solution to my case which seems to be working satisfactorily.
The key appears to be that the first view added to the UIWindow is the only view properly initialized. All the problems I've had tend to stem from incorrect notification of the orientation of the device. The first view added, apparently has this correctly configured.
In my case I didn't want the UISplitView as the first view. The following is working for me.
The app delegate application:didFinishLaunching method is special. Adding the view to the UIWindow must occur here. If it is done elsewhere it does not get configured properly.
Essentially the magic sauce, is have the split view be the first view added to the window. Its then ok to remove it as long as you retain the UISplitViewController. From then on you can swap other views in and out, including the UISplitView and most things seem to be ok.
I've still run into a few issues. Popovers on views other than the split view are confused on the views frames and location of toolbar buttons and will display in the wrong location. I place then in a specific location and that seems to handle that case.
If a popover on the split view is still displayed, and you try to view another view, the orientation of the second view is confused and shows up sideways. If that view is accessed before the popup is displayed, all is well. I've fixed this my manually dismissing the popover before switching to any other view.
Here's the code if it helps. All the controllers are instance variables of appDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// This also seems to work as good magic. Seems to set orientation and size properties that persist.
[window addSubview:splitViewController.view];
[splitViewController.view removeFromSuperview];
[self switchToNewViewController:firstController];
[window makeKeyAndVisible];
return TRUE;
}
- (void)switchToNewViewController:(UIViewController *)newViewController {
[popoverController dismissPopoverAnimated:FALSE];
if (newViewController != currentViewController) {
[currentViewController removeFromSuperview];
currentViewController = newViewController;
[window addSubView:newViewController.view];
}
}
Just wanted to say that I was running into these same issues, found this forum topic, and followed the advice from g051051 above. This is working perfectly for me. I am not seeing any glitch, and no messages about wait_fences in the console of the device.
I simply used IB to create two UIWindow objects in the main XIB, created as normal the UISplitViewController and then also an instance of my other controller derived from UIViewController (which I am using for full screen display). I have simply hooked them up by attaching the rootViewController for each UIWindow to its appropriate controller.
In application:didLaunch...: method I can decide which window to send the makeKeyAndVisible method and which to set to hidden. When the user want to switch back and forth I simply have to send makeKeyAndVisible to one and set the hidden property on the other, that's all there is to it.
As indicated all of the rotation related messages are sent to each controller appropriately, regardless of which one is associated with the currently visible window.
Anyway, works great for me, and actually quite easy to set up.
The app in question has a MainView->ModalView pair. The ModalView is shown via UIModalTransitionStyleFlipHorizontal. In case of didReceiveMemoryWarning, MainView is dumped (since it is not visible) and the app stays "alive" but when you flip back there is a (very) short period of time when the screen is blank (since the modal dialog is returning to a now-deallocated view). When the animation transition is over, MainView is regenerated and all is ok.
I just would like to somehow regenerate MainView before returning from ModalView (in case of a memory warning).
Is this a good idea? Am I doing something wrong as far as the warning is concerned?
Thanks
You might want to try to reload your MainView, before you start the flip, so that there is no blank screen to wait for. That does mean that your flip will be delayed, but maybe that is better?
If you want to reload your MainView before you head to it, try to access MainView like this
if (MainView)
....
if the MainView is a view or like this
if (MainView.view)
.....
if the MainView is a view controller. What the access of the view does is to force a reload of that view from the NIB, or loadView.
You can also choose to ignore the memory warning by commenting out the section in DidReceiveMemoryWarning - do at your own risk though :)