新iPad:低内存警告没有出现?

Way*_*man 21 memory-management ios ipad-3

我一直在开发一个非常图形密集的iPad应用程序.我已经能够在iPad 2上挤出相当多的性能,但新iPad的@ 2x显卡在内存部门打包了很多.使用仪器中的活动监视器我能够看到我的应用程序的大小迅速增加到300MB-400MB范围,但我没有收到任何低内存通知.我使用a UINavigationController来管理我的视图,因此进入堆栈会对内存产生累积影响,最终会终止.我没有在iPad 2上遇到这个问题,我收到了预期的低内存通知.我的应用程序已被编码为尽可能清理并在该设备上表现良好.

我已经阅读了一些类似的问题:

IOS应用程序因低内存而被杀,但没有内存警告收到
iPhone应用程序使用150 MB内存,仍然没有低内存警告!

这些建议似乎都没有帮助.

我插入了代码以强制发送低内存通知:

[[UIApplication sharedApplication] _performMemoryWarning];
Run Code Online (Sandbox Code Playgroud)

这会导致非活动视图按预期卸载并将内存消耗恢复正常.这使用私有API并且是hack,因此出于实际原因不是解决方案. 如何让我的设备正确响应低内存条件,让我的应用程序知道它需要清理?

rob*_*ash 12

我联系了Apple支持部门来解决我的内存问题,并询问了iPad 3上的低内存警告:

- 因为主线程上传递了内存警告,如果它阻止主线程,你的应用程序将不会收到内存警告.

- 即使您的应用程序没有阻止主线程,内存使用量也可能快速增长,以至于在应用程序被杀死以释放内存之前不会传递内存警告.

- 当内核在各种内存压力级别之间转换时,会触发内存警告.因此,应用程序通常会收到内存警告,然后在内存耗尽时将其杀死很长时间.初始内存警告释放了足够的内存以使应用程序保持活动状态,但不足以让内核转换到较低级别的内存压力.

因此,内存警告应被视为有关硬件状态的有用数据,并且是应用程序在给定设备上应使用多少内存的良好指南,但不应依赖于作为防止应用程序的工具从被杀

也许这有助于......


Way*_*man 2

此问题已在 iOS 5.1.1 中得到修复。对于使用 5.1 的用户,我实现了自己的内存看门狗,并发出类似于发出实际内存警告时使用的通知。

我首先在 上创建了一个类别UIApplication。这会发布一个UIImage监听(或无论其后备缓存是什么)的通知来卸载缓存的图像。

。H

@interface UIApplication (ForceLowMemory)

+ (void) forceUnload;

@end
Run Code Online (Sandbox Code Playgroud)

.米

#import "UIApplication+ForceLowMemory.h"

@implementation UIApplication (ForceLowMemory)

+ (void)forceUnload {
    [[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationDidReceiveMemoryWarningNotification 
                                                        object:[UIApplication sharedApplication]];
}

@end
Run Code Online (Sandbox Code Playgroud)

接下来,我创建了一个内存管理器看门狗,如下所示:

。H

@interface ELMemoryManager : NSObject

- (void)startObserving;
- (void)stopObserving;

+ (ELMemoryManager*) sharedInstance;

@end
Run Code Online (Sandbox Code Playgroud)

.米

#import "ELMemoryManager.h"
#import "UIApplication+ForceLowMemory.h"
#import <mach/mach.h>

@interface ELMemoryManager()

@property (nonatomic, retain) NSTimer *timer;
uint report_memory(void);

@end

#define MAX_MEM_SIZE 475000000

@implementation ELMemoryManager
@synthesize timer = timer_;

static ELMemoryManager* manager;

#pragma mark - Singleton

+ (void) initialize {
    if (manager == nil) {
        manager = [[ELMemoryManager alloc] init];
    }
}

+ (ELMemoryManager*) sharedInstance {
    return manager;
}

#pragma mark - Instance Methods

uint report_memory(void) {
    struct task_basic_info info;
    mach_msg_type_number_t size = sizeof(info);
    kern_return_t kerr = task_info(mach_task_self(),
                                   TASK_BASIC_INFO,
                                   (task_info_t)&info,
                                   &size);
    if( kerr == KERN_SUCCESS ) {
        return info.resident_size;
    } else {
        return 0;
    }
}

- (void)startObserving {
    if (!self.timer) {
        NSTimer* timer = [NSTimer scheduledTimerWithTimeInterval:5.0f target:self selector:@selector(checkMemory:) userInfo:nil repeats:YES];
        self.timer = timer;
    }
    [self.timer fire];
}

- (void)stopObserving {
    [self.timer invalidate];
    self.timer = nil;
}

- (void)checkMemory:(id)sender {
    uint size = report_memory();
    if (size > MAX_MEM_SIZE) {
        NSLog(@"we've busted the upper limit!!!");
        [UIApplication forceUnload];
    }
}

#pragma mark - Memory Management
- (void)dealloc {
    [self.timer invalidate];
    [timer_ release];
    [super dealloc];
}

@end
Run Code Online (Sandbox Code Playgroud)