ChatGPT解决这个技术问题 Extra ChatGPT

iOS Development: How can I induce low memory warnings on device?

I'd like to test my app functions well in low memory conditions, but it's difficult to test. How can I induce low memory warnings that trigger the didReceiveMemoryWarning method in my views when the app is running on the device, not the simulator? Or what are some ways I can test my app under these possible conditions?

The reason I can't use the simulator is my app uses Game Center and invites don't work on the simulator.


E
Enzo Tran

You can call the private method:

[[UIApplication sharedApplication] performSelector:@selector(_performMemoryWarning)];

Just remember to use it on debug only, or else your app will get rejected.


It appears this code accurately simulates the memory warning on the device. Thanks Enzo!
Instead of using this in code, execute it in the debugger. Just hit pause and enter po [[UIApplication sharedApplication]performSelector:@selector(_performMemoryWarning)]
Rather than using po, use expr, i.e. expr (void)[[UIApplication sharedApplication] performSelector:@selector(_performMemoryWarning)];
In the debugger, you don't need to use the workaround for not having the header: expr (void)[[UIApplication sharedApplication] _performMemoryWarning]
For anyone who is looking to do this with Swift: type expr UIApplication.sharedApplication().performSelector("_performMemoryWarning") instead of using the usual #selector
C
CopsOnRoad

The iOS Simulator's Simulate Memory Warning menu item allows you to simulate a memory warning.

https://i.stack.imgur.com/UFz9B.png


Only way to check it on the device is to actually force it, ie by using the app for long periods of time or intensive images or what have you, will vary app to app. A suggestion might be to use an older device (3g perhaps?) instead of an iPhone 4 to help you get to the warning faster.
Thanks, Jesse, I think I'm just gonna add some hacks to my app to simulate invites so that I can run it in the simulator and induce the memory warnings that way.
Question was about the simulation on device.
T
ThomasW

Using Instruments, use the menu item: Instrument -> Simulate Memory Warning.

To use Instruments on your app from Xcode, use the Product -> Profile menu item.


@OrangeDog What's happening?
Well, nothing. When I use Enzo's answer views have to reload when I return to them, not so using this method.
C
ChikabuZ

I've re-written Enzo Tran's answer in Swift:

UIControl().sendAction(Selector(("_performMemoryWarning")), to: UIApplication.shared, for: nil)

Thanks! Xcode warns of "no method declared with Objective-C selector", but this works nonetheless.
B
Blazej SLEBODA

If someone, for whatever reason, tries to do this in Swift 4 - here is how to allocate 1.2 GB of ram.

let d = Data.init(repeating: 100, count: 1200000000)

This is helpful to trigger a warning alert in other apps


Will doing something like this obfuscate the actual memory information I'm trying to view in Instruments? While I see there isn't a proper way to do this on a physical device, if my point is to see what is taking up my memory within my app it seems like this is going to skew all of the data and I'll no longer have a relative answer. I'll still see what is taking up more, but not the true proportions.
this crashes immediately
B
BinaryStar

To test on a device, just add some code that periodically allocates large chunks of memory without freeing it (i.e. leak on purpose). You can do this in a separate thread, or in response to a timer, or using whatever mechanism that best allows you to test and observe the behavior of your application.

You might also choose to create a separate app that does something similar and is designed to run in the background, if you'd like to easily reuse this and/or test with multiple applications.


not very practical. the solution to call a private method for testing is better
Not a good solution if you want to look at real world scenario. You are crippling the app due to a leak not due to memory pressure. That is bad since what you want to do is test how the app responds in high memory pressure state. On the downside its harder to figure out what the problem is a real leak or the fake one you introduced. The private method one is better for testing as given below.
This answer should not be downvoted, as the second paragraph is actually what Apple says to do if you want to test your app's behavior when memory really gets low.
Answer would be improved with a code block to perform this allocation!
Although it takes more work to setup, this is a more realistic test than calling the private method. When there really is critical memory pressure, will your app be able to perform the actions you tell it to do? And will those actions relieve the situation or make it worse and cause iOS to terminate it? Besides, the private method does not work for testing DISPATCH_SOURCE_TYPE_MEMORYPRESSURE.
C
Csabi

Converted @ChikabuZ to swift 3:

UIControl().sendAction(Selector(("_performMemoryWarning")), to: UIApplication.shared, for: nil)

D
Daniel A. White

Theres a menu command that will invoke it.

Hardware > Simulate Memory Warning from the simulator.


Question was about the simulation on device.
In Xcode 10 it's now under Debug > Simulate Memory warning.
p
ph1lb4

If someone, for whatever reason, tries to do this in Swift 3 - here is how to allocate 1.2 GB of ram.

   for i in 0...1200 {
      var p: [UnsafeMutableRawPointer] = []
      var allocatedMB = 0
      p.append(malloc(1048576))
      memset(p[allocatedMB], 0, 1048576);
      allocatedMB += 1;
   }

let d = Data.init(repeating: 100, count: 1200000000)
@Adobels you should post that as an answer :)
V
Vishal Chaudhry

Swift 4:

UIApplication.shared.perform(Selector(("_performMemoryWarning")))

Can execute the above in response to an event/notification.