MKMapView memory issue in iOS SDK - iphone

In my app, I've noticed that as I push and pop a view controller containing an MKMapView, memory usage steadily increases. I've determined that there is a problem with MapKit itself, not my code, though. I made a test project containing simply a navigation controller in which I repeatedly can push and pop a view controller containing nothing but a map view - no annotations or overlays.
My results indicate that this is a bug in iOS 6; in the iOS 6 simulator I see the gradual increase in memory usage. I suppose this is an issue with Apple's new in-house maps.
Any thoughts as to why this is happening?

If you push and pop the MKMapView in code over and over, you might want to make sure that you are letting control back to iOS so that it can actually release the view (Not putting the push and pop in a while(1) loop that is).
Maybe you should try turning off ARC and make explicit retain and release calls to the map view and see if you get better results, just as an experiment?

Related

Alternative way to load ViewControllers on a UIPageControl

In my project I'm using a UIPageControl as a container UIViewController for scrolling. I used this tutorial (using ARC and storyboards): http://www.wannabegeek.com/?p=168 and the source code: https://github.com/wannabegeek/PageViewController
As you can see there are 3 ViewControllers in the project, and they are added as child on the CustomPagerViewController. In that project there are only 3 ViewControllers that are added, but in my project I got more than 3 ViewControllers and I also reuse them with another text, image, label, etc. on it. The problem is that in the project all those ViewControllers are getting loaded whenever the CustomPagerViewController is loaded and this costs memory so I'm looking for another way how I can deal with this problem instead of loading them all at once?
You shouldn't try to optimise controller allocation in this way. Obviously retaining view controllers in memory takes up space, but believe me, not that much.
We have to difference here between the controller and its view. Views can take up a lot of memory in order to get themselves displayed on screen, but iOS already has its own mechanisms to free this memory when it's no longer required (ie: the view is not on screen / doesn't have a window).
iOS view controllers used to free views memory by themselves (this behaviour was in [UIViewControllers didReceiveMemoryWarning]), but that's no longer the case in iOS 6. Now you're responsible for doing so in you feel like it's needed by your app. Bear in mind that despite nilling these views in this method (or dealloc), you won't be saving much memory, as most part of the (graphical) resources used to display a view in screen may have already been released by iOS, and the amount of memory you may end up freeing close to 0.
To sum up, in your case I'd convert PagerViewController into a proper iOS container controller using this guide. The key is to call the following methods:
[UIViewController addChildViewController:]
[UIViewController willMoveToParentViewController]
[UIViewController removeFromParentViewController]
[UIView addSubview:]
[UIView removeFromSuperview]
in the right order according to your needs. In your case, you can add / remove these in the scrollViewDidScroll method. Use them in this way, and let Apple's magic happen.
You might as well use UIPageViewController which gives you some nice out-of-the-box features.

"viewWillAppear" not call in xcode 4.5 with iPhone 4.3 simulator

"viewWillAppear" not call in xcode 4.5 with iphone 4.3 simulator, but if it runs in iPhone 5.0 or iPhone 6.0 simulator, this method will be called.
why? and what can i do if i want to do something when the view of an controller will appear in ios 4.3?
I think it may be related to the "View Controller Abusing". Check if your container view controller is used correctly. You can refer to this post for detail.
Based on your comments, the problem appears to be the lack of container view controllers in iOS 4. As of 5+ you're explicitly meant to be able to add the view of any controller into the view of any other* and that will generate the appropriate view[Will/Did]Appear, along with all the other newer messages — viewDidLayoutSubviews, etc.
In 4 you weren't explicitly allowed to build container view controllers and there's no deliberate, specific backwards link that connects a view back to its controller.
As a result, when you add the navigation controller to your view it doesn't get viewDidAppear. Because it doesn't know that its view has appeared, it doesn't tell any of the controllers it contains that their views have appeared.
Probably the best you're going to be able to do is to hack around that by (i) checking if you're operating under iOS 4; and (ii) if so, posting artificial viewWillAppear/viewDidAppear/viewWillDisappear/viewDidDisappear to your contained controllers.
Based on personal experience, iOS 4 (at least in 4.3) does actually implement addChildViewController: but not to do what the later, documented version does. So despite it not being an entirely accurate functionality check I tend to use if([self respondsToSelector:#selector(presentingViewController)]) to determine whether I need to propagate these messages manually.
[*] and you should also call addChildViewController: to make sure all messages move correctly in all directions

App is locking up iOS but no memory leaks are reported

Having a strange issue with my app where the entire iOS device gets locked up and the only thing I can do is restart the device. I am not seeing any exceptions getting thrown, nor am I seeing any memory leaks in Instruments.
The app has a navigation controller with a main menu. I then push a viewcontroller that has a grid of images being loaded. If I go back and forth between the main menu and the grid the app will crash after ~15 times. However, it isn't just the app that's killed, it's the entire OS which is something I've never seen.
At first I thought I was leaking memory, but Leaks isn't showing anything. I'm playing around with Allocations and I'm seeing that the grid view controller allocation count just keeps going up. The app is using ARC, which I don't like that much because it's too "magical", but I assumed it would be cleaning up properly.
One thing that concerns me is that viewDidUnload nor dealloc is being called on my grid view controller after it popped from the nav controller, so I'm never explicitly cleaning up my images or killing network connections. I assume this is where the issue is at but I don't know when I should kill these because the usual places to clean up (ie. viewDidUnload, dealloc) aren't being called.
This is happening on iPhone and iPad both running 5.1 and I'm using the AFNetworking UIImageView category to load images.
Cheers,

iOS 3.1.2 [UIViewController dismissModalViewControllerAnimated:] creates infinite recursion

I have some code that works fine on my iPod Touch running some 4.0-series iOS as well as the simulator that comes with the iOS SDK 4.1. But when I call [UIViewController dismissModalViewController:] on an iPhone 2 running iOS 3.1.2 it get an infinite recursion, eventually crashing.
I have a view controller that opens a table view where the user selects a document to open. Upon selecting a document my table view controller's delegate calls the parent view controllers dismissModalViewController method. I think it is because I'm closing the view controller whose code is running that causes this.
dismissModalViewController is documented to be available in iOS 2.0 and later.
How can I close the UIViewController that's open from its own code?
I figured my problem might be heap corruption from some previous code. A way to debug that is to comment off snippets of previous code to see whether the bug would go away or come back. Almost immediately I found that I was calling dismissModalViewControllerAnimated: on the current view controller's parent controller. Why that works in iOS 4.x I have no idea. The problem I face is that I have two modal dialogs that I need to close simultaneously, which I cannot get working, but that is a different question.

iPhone rotation causes memory warning

I am introducing auto-rotation to my app and I'm having an issue with a memory warning. Whatever orientation I start my app in, as long as the device remains in that orientation, I get no memory warnings. However, the first time I rotate the device the following warning is placed on the console: Safari got memory level warning, killing all documents except active. When this happens all view controllers, other than the one be viewed, are unloaded - this produces unexpected behaviors when navigating back to view controllers that should normally already be on the stack. The app never crashes and this warning occurs once upon the first rotation, after that it never happens (until I stop/start the app again). Also, this only happens on the device - no memory warning when running in simulator.
Has anyone seen this behavior? In any case, does anyone have any suggestions on what I might try in order to remove the memory warning.
Thanks in advance.
You can't assume that memory warnings will never happen; you have to handle them gracefully. Suggestions:
Check for memory leaks with Leaks (note that it doesn't catch all leaks).
Fix your view controllers to handle a view reload. Specifically (unless you override -(void)loadView), it'll call -(void)viewDidUnload on a memory warning and -(void)viewDidLoad when it becomes visible again. You might fix this by saving state in the view controller and restoring it to the views in -(void)viewDidLoad.
If you can't be bothered handling the memory warning, implement -(void)didReceiveMemoryWarning and do not super-call (i.e. comment out [super didReceiveMemoryWarning]). This is lazy, and might cause a crash if your app ends up using too much memory (background apps like Safari and Phone will be killed first).
You can test memory warning behaviour with the "simulate memory warning" option in the simulator.
Memory warnings are part of a normal iOS behavior, due to its limited memory, especially now that multi-tasking is supported.
UIKit doesn’t only allow navigation back from a view controller, but also allows navigation to other view controllers from existing ones. In such a case, a new UIViewController will be allocated, and then loaded into view. The old view controller will go off-screen and becomes inactive, but still owns many objects – some in custom properties and variables and others in the view property/hierarchy. And so does the new visible view controller, in regard to its view objects.
Due to the limited amount of memory of mobile devices, owning the two sets of objects – one in the off-screen view controller and another in the on-screen view controller – might be too much to handle. If UIKit deems it necessary, it can reclaim some of the off-screen view controller’s memory, which is not shown anyway; UIKit knows which view controller is on-screen and which is off-screen, as after all, it is the one managing them (when you call presentModalViewController:animated: or dismissModalViewControllerAnimated:). So, every time it feels pressured, UIKit generates a memory warning, which unloads and releases your off-screen view from the view hierarchy, then call your custom viewDidUnload method for you to do the same for your properties and variables. UIKit releases self.view automatically, allowing us then to manually release our variables and properties in our viewDidUnload code. It does so for all off-screen view controllers.
When the system is running out of memory, it fires a didReceiveMemoryWarning. Off-screen views will be reclaimed and released upon memory warning, but your on-screen view will not get released – it is visible and needed. In case your class owns a lot of memory, such as caches, images, or the like, didReceiveMemoryWarning is where you should purge them, even if they are on-screen; otherwise, your app might be terminated for glutting system resources. You need to override this method to make sure you clean up your memory; just remember you call [super didReceiveMemoryWarning];.
An even more elaborate explanation is available here: http://myok12.wordpress.com/2010/11/30/custom-uiviewcontrollers-their-views-and-their-memory-management/