MKMapView autorelease not calling dealloc after UIViewController is popped
Use Instruments to track the retain/release history of CustomAdvancedGPSMapViewController
and/or MKMapView
:
In Xcode, select "Product > Profile" from the menu.
When Instruments starts, select the "Allocations" template.
If your app starts automatically, click the "Stop" button to stop it.
Click the "i" button on the Allocations instrument, and check "Record reference counts".
Select "View > Extended Detail" from the menu.
Click the "Record" button to start your app, and wait for your app to start in the simulator.
In the simulator, use your app to navigate to the CustomAdvancedGPSMapViewController.
In Instruments, click the "Pause" button
Use the search field in the top-right of the window and search for CustomAdvancedGPSMapViewController. CustomAdvancedGPSMapViewController should appear in the Allocation Summary list.
In the Allocation Summary list, Click the -> arrow next to the CustomAdvancedGPSMapViewController name. This should show that you have one instance of CustomAdvancedGPSMapViewController active in your app.
Click the -> arrow next to address. This will display the retain/release history for this CustomAdvancedGPSMapViewController instance.
Un-pause Instruments, return to the simulator, and dismiss your CustomAdvancedGPSMapViewController and return to the point where you believe the controller should be deallocated.
Return to Instruments, click "Pause" again, and look at the updated retain/release history.
The first event in the retain/release history should be "malloc". Select this row and the Extended Detail view in the right side of the window will display the stack trace for this allocation. You should see your own code in the stack trace. Double-click your code in the stack trace and you should see your line of code that allocated the the CustomAdvancedGPSMapViewController instance.
Above the code view, click the "History" tab to return to the history list.
The last event in the retain/release history should be "free". If that's not the case there may be a leak. Inspect the retain/release history and look for an unmatched retain. There may be a lot of noise, related to CoreAnimation, etc. Look for events in which your code appears in the stack trace.
Compare the retain/release history with a different view controller that is not leaking.
If CustomAdvancedGPSMapViewController
isn't leaking, try inspecting the history of MKMapView
.
how to manage memory allocation issue in ios ARC proejct
XCode has a built-in memory profiler that can help you with this issue - for a tutorial on how to use it, this might be helpful http://www.raywenderlich.com/23037/how-to-use-instruments-in-xcode
Otherwise, if dealloc isn't being called it could be a symptom of a retain cycle (two objects maintain strong references to each other, so they are never deallocated).
Memory not being released for MKMapView w/ ARC
As it turns out, there is a known bug with iOS 6 and MKMapView
not releasing it's memory correctly. Unfortunately there is no real fix other than trying to force the map view to purge it's cache which doesn't have that great of an impact on releasing memory.
The strange thing is that even when the app is receiving memory warnings, the map view cache is still not being purged properly. Eventually, the app becomes unstable and is killed by the OS.
Apple has been getting very sloppy with their testing lately. This is the second bug with MKMapView
that I've come across (the other being mapViewDidFinishLoadingMap:
being called early) and both bugs have been really obvious to catch if they had just done some performance and sanity testing.
Here is some code which may help:
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
// This is for a bug in MKMapView for iOS6
[self purgeMapMemory];
}
// This is for a bug in MKMapView for iOS6
// Try to purge some of the memory being allocated by the map
- (void)purgeMapMemory
{
// Switching map types causes cache purging, so switch to a different map type
detailView.mapView.mapType = MKMapTypeStandard;
[detailView.mapView removeFromSuperview];
detailView.mapView = nil;
}
The other thing you could do is use one instance of the MKMapView
throughout your entire app and that should help minimize how much memory is allocated each time the view is shown since the map view will already be allocated.
SwiftUI - memory leak in NavigationView
You don't need to split the close button out in its own view. You can solve this memory leak by adding a capture list to the NavigationView's closure: this will break the reference cycle that retains your viewModel
.
You can copy/paste this sample code in a playground to see that it solves the issue (Xcode 11.4.1, iOS playground).
import SwiftUI
import PlaygroundSupport
struct ModalView: View {
@Environment(\.presentationMode) private var presentation
@ObservedObject var viewModel: ViewModel
var body: some View {
// Capturing only the `presentation` property to avoid retaining `self`, since `self` would also retain `viewModel`.
// Without this capture list (`->` means `retains`):
// self -> body -> NavigationView -> Button -> action -> self
// this is a retain cycle, and since `self` also retains `viewModel`, it's never deallocated.
NavigationView { [presentation] in
Text("Modal is presented")
.navigationBarItems(leading: Button(
action: {
// Using `presentation` without `self`
presentation.wrappedValue.dismiss()
},
label: { Text("close") }))
}
}
}
class ViewModel: ObservableObject { // << tested view model
init() {
print(">> inited")
}
deinit {
print("[x] destroyed")
}
}
struct TestNavigationMemoryLeak: View {
@State private var showModal = false
var body: some View {
Button("Show") { self.showModal.toggle() }
.sheet(isPresented: $showModal) { ModalView(viewModel: ViewModel()) }
}
}
PlaygroundPage.current.needsIndefiniteExecution = true
PlaygroundPage.current.setLiveView(TestNavigationMemoryLeak())
Related Topics
How to Get Class Name of Parent Viewcontroller in Swift
Delegate Using Container View in Swift
Load a Pcm into a Avaudiopcmbuffer
Format Float Value with 2 Decimal Places
How to Install Swift Package via Package Manager
Change What Print(Object) Displays in Swift 2.0
Error Using Associated Types and Generics
Swift Combine - Wait for All Publishers
What Is the Nsfont Name for the Font 'Sf Mono'
Xcode 11 Doesn't Recognize Core Data Entity
Get a Unique String for a Given Anyobject
Making Cocoa Application Scriptable Swift
Convert Int to Uint32 in Swift
How to Navigate to a New View from Navigationbar Button Click in Swiftui