I am receiving memory warnings in didReceiveMemoryWarning. I know memory warnings have different levels like level-1,level-2. Is there any way determine the warning level? Example:
if(warning level == 1)
<blah>
I am receiving memory warnings in didReceiveMemoryWarning. I know memory warnings have different levels like level-1,level-2. Is there any way determine the warning level? Example:
if(warning level == 1)
<blah>
Hope this helps!!!
There are 4 levels of warnings (0 to 3). These are set from the kernel memory watcher, and can be obtained by the not-so-public function OSMemoryNotificationCurrentLevel().
typedef enum {
OSMemoryNotificationLevelAny = -1,
OSMemoryNotificationLevelNormal = 0,
OSMemoryNotificationLevelWarning = 1,
OSMemoryNotificationLevelUrgent = 2,
OSMemoryNotificationLevelCritical = 3
} OSMemoryNotificationLevel;
How the levels are triggered is not documented. SpringBoard is configured to do the following in each memory level:
Warning (not-normal) — Relaunch, or delay auto relaunch of nonessential background apps e.g. Mail.
Urgent — Quit all background apps, e.g. Safari and iPod.
Critical and beyond — The kernel will take over, probably killing SpringBoard or even reboot.
My first advice would be to research the memory warning notification in the docs (e.g., what are the contents of its userInfo
dictionary, if present). I don't know if it provides any details or not.
But ultimately, you shouldn't speculate on the level of the memory warning, just assume the worst and release as much unused data as you can.
There is no (public, working) way to get the current memory pressure level from the system on a customer device. There is however a way to get notified of memory pressure changes using the Dispatch Source API.
Memory pressure dispatch sources can be used to notify an application of changes to memory pressure. This can be more fine-grained than the notifications provided by UIKit and includes the capability to be notified when memory pressure returns to normal.
For example:
Objective-C:
dispatch_source_t memorySource = NULL;
memorySource = dispatch_source_create(DISPATCH_SOURCE_TYPE_MEMORYPRESSURE, 0L, (DISPATCH_MEMORYPRESSURE_NORMAL | DISPATCH_MEMORYPRESSURE_WARN | DISPATCH_MEMORYPRESSURE_CRITICAL), [self privateQueue]);
if (memorySource != NULL) {
dispatch_block_t eventHandler = dispatch_block_create(DISPATCH_BLOCK_ASSIGN_CURRENT, ^{
if (dispatch_source_testcancel(memorySource) == 0 ){
dispatch_source_memorypressure_flags_t memoryPressure = dispatch_source_get_data(memorySource);
[self didReceiveMemoryPressure:memoryPressure];
}
});
dispatch_source_set_event_handler(memorySource, eventHandler);
dispatch_source_set_registration_handler(memorySource, eventHandler);
[self setSource:memorySource];
dispatch_activate([self source]);
}
Swift 4:
if let source:DispatchSourceMemoryPressure = DispatchSource.makeMemoryPressureSource(eventMask: .all, queue:self.privateQueue) as? DispatchSource {
let eventHandler: DispatchSourceProtocol.DispatchSourceHandler = {
let event:DispatchSource.MemoryPressureEvent = source.data
if source.isCancelled == false {
self.didReceive(memoryPressureEvent: event)
}
}
source.setEventHandler(handler:eventHandler)
source.setRegistrationHandler(handler:eventHandler)
self.source = source
self.source?.activate()
}
Note that the event handler is also being used as the "registration handler". This will cause the event handler to fire when the dispatch source is activated, effectively telling the application of what the "current" value is when the source is activated.