How to detect memory warnings in iOS App Extension

2.1k Views Asked by At

I'm writing an iOS extension that extends NEPacketTunnelProvider in the NetworkExtension framework released in iOS 9. I'm running into a situation where iOS is killing the extension once hits 6MB of memory used.

In a regular iOS app, there are two ways to detect memory warnings and do something about it. Either via [UIApplicationDelegate applicationDidReceiveMemoryWarning:(UIApplication*)app] or [UIViewController didReceiveMemoryWarning]

Is there a similar way to detect memory warnings within an extension? I've searched up and down the iOS extension documentation but have come up empty thus far.

2

There are 2 best solutions below

3
Ozgur Vatansever On BEST ANSWER

I am not very familiar with the extensions API, however my basic hunch says that you can register any of your object as observers of UIApplicationDidReceiveMemoryWarningNotification from within that class:

NSNotificationCenter.defaultCenter().addObserverForName(UIApplicationDidReceiveMemoryWarningNotification,
  object: nil, queue: .mainQueue()) { notification in
    print("Memory warning received")
}
0
Kannan Chandrasegaran On

ozgur's answer does not work. UIApplicationDidReceiveMemeoryWarningNotification is a UIKit event and I haven't found a way to get access to that from an extension. The way to go is the last of these options: DISPATCH_SOURCE_TYPE_MEMORYPRESSURE.

I've used the following code (Swift) in a Broadcast Upload Extension and have confirmed with breakpoints that it is called during a memory event right before the extension conks out.

let source = DispatchSource.makeMemoryPressureSource(eventMask: .all, queue: nil)

let q = DispatchQueue.init(label: "test")
q.async {
    source.setEventHandler {
        let event:DispatchSource.MemoryPressureEvent  = source.mask
        print(event)
        switch event {
        case DispatchSource.MemoryPressureEvent.normal:
            print("normal")
        case DispatchSource.MemoryPressureEvent.warning:
            print("warning")
        case DispatchSource.MemoryPressureEvent.critical:
            print("critical")
        default:
            break
        }
        
    }
    source.resume()
}