【问题标题】:Web App for iPad memory warning适用于 iPad 内存警告的 Web 应用程序
【发布时间】:2013-08-17 20:46:35
【问题描述】:

我正在开发一个使用 html5、css3 和 jquery 作为应用程序的 Web 应用程序。我们通过 XCODE 运行 web 文件,并使用 XCODE 将“应用程序”上传到 iPad。

最近我们在启动画面旋转几秒钟后收到内存警告和崩溃。

应用程序在 XCODE 模拟器中运行良好,我们注意到当应用程序有视频文件(即使是像 800KB 这样的小文件)时似乎会发生这种情况。

这是在 iPad 上运行应用程序的控制台。

我们如何防止这种崩溃?

8 月 15 日 11:50:12 BD-Graphics-Lab-6-iPad3 BD 按钮[4020] :多任务->设备:是,应用程序:是 8月15日 11:50:12 BD-Graphics-Lab-6-iPad3 内核[0]:launchd[4020] 内置 配置文件:容器(沙盒)

8 月 15 日 11:50:12 BD-Graphics-Lab-6-iPad3 内核 [0] :启动 [4020] 容器: /private/var/mobile/Applications/997C5F22-C5A6-4A05-96C8-8ABEA9DAAC8A (沙盒)

8 月 15 日 11:50:12 BD-Graphics-Lab-6-iPad3 BD 推送 按钮[4020]:由于页面加载而重置插件。

8 月 15 日 11:50:15 BD-Graphics-Lab-6-iPad3 BD 按钮[4020]: 收到内存警告。

8 月 15 日 11:50:17 BD-Graphics-Lab-6-iPad3 UserEventAgent [13]:jetsam:内核终止快照正在 已创建

8 月 15 日 11:50:17 BD-Graphics-Lab-6-iPad3 com.apple.launchd1 (UIKitApplication:com.bd.Push.us.y[0x4721][4020]): (UIKitApplication:com.bd.Push.us.y[0x4721]) 退出:杀死:9

8 月 15 日 11:50:17 BD-Graphics-Lab-6-iPad3 backboardd[26] : 应用 'UIKitApplication:com.bd.Push.us.y[0x4721]' 异常退出 信号 9:杀死:9

8 月 15 日 11:50:17 BD-Graphics-Lab-6-iPad3 报告崩溃[4021]:libMobileGestalt copySystemVersionDictionaryValue:无法从中查找 ReleaseType 系统版本字典

8 月 15 日 11:50:17 BD-Graphics-Lab-6-iPad3 ReportCrash[4021]:保存崩溃报告到 /Library/Logs/CrashReporter/LowMemory-2013-08-15-115017.plist 使用 uid:0 gid:0,synthetic_euid:0 egid:0

AppDelegate.m

@implementation AppDelegate

@synthesize window, viewController;

- (id)init
{
    /** If you need to do any extra app-specific initialization, you can do it here
     *  -jm
     **/
    NSHTTPCookieStorage* cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];

    [cookieStorage setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways];

    int cacheSizeMemory = 8 * 1024 * 1024; // 8MB
    int cacheSizeDisk = 32 * 1024 * 1024; // 32MB
#if __has_feature(objc_arc)
        NSURLCache* sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:cacheSizeMemory diskCapacity:cacheSizeDisk diskPath:@"nsurlcache"];
#else
        NSURLCache* sharedCache = [[[NSURLCache alloc] initWithMemoryCapacity:cacheSizeMemory diskCapacity:cacheSizeDisk diskPath:@"nsurlcache"] autorelease];
#endif
    [NSURLCache setSharedURLCache:sharedCache];

    self = [super init];
    return self;
}

#pragma mark UIApplicationDelegate implementation

/**
 * This is main kick off after the app inits, the views and Settings are setup here. (preferred - iOS4 and up)
 */
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
    int cacheSizeMemory = 16*1024*1024; // 16MB
    int cacheSizeDisk = 32*1024*1024; // 32MB
    NSURLCache *sharedCache = [[[NSURLCache alloc] initWithMemoryCapacity:cacheSizeMemory diskCapacity:cacheSizeDisk diskPath:@"nsurlcache"] autorelease];
    [NSURLCache setSharedURLCache:sharedCache];
    
    CGRect screenBounds = [[UIScreen mainScreen] bounds];

#if __has_feature(objc_arc)
        self.window = [[UIWindow alloc] initWithFrame:screenBounds];
#else
        self.window = [[[UIWindow alloc] initWithFrame:screenBounds] autorelease];
#endif
    self.window.autoresizesSubviews = YES;

#if __has_feature(objc_arc)
        self.viewController = [[MainViewController alloc] init];
#else
        self.viewController = [[[MainViewController alloc] init] autorelease];
#endif
    self.viewController.useSplashScreen = YES;

    // Set your app's start page by setting the <content src='foo.html' /> tag in config.xml.
    // If necessary, uncomment the line below to override it.
    // self.viewController.startPage = @"index.html";

    // NOTE: To customize the view's frame size (which defaults to full screen), override
    // [self.viewController viewWillAppear:] in your view controller.

    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];

    return YES;
}

// this happens while we are running ( in the background, or from within our own app )
// only valid if flush.ca.mbp-Info.plist specifies a protocol to handle
- (BOOL)application:(UIApplication*)application handleOpenURL:(NSURL*)url
{
    if (!url) {
        return NO;
    }

    // calls into javascript global function 'handleOpenURL'
    NSString* jsString = [NSString stringWithFormat:@"handleOpenURL(\"%@\");", url];
    [self.viewController.webView stringByEvaluatingJavaScriptFromString:jsString];

    // all plugins will get the notification, and their handlers will be called
    [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPluginHandleOpenURLNotification object:url]];

    return YES;
}

// repost the localnotification using the default NSNotificationCenter so multiple plugins may respond
- (void)            application:(UIApplication*)application
    didReceiveLocalNotification:(UILocalNotification*)notification
{
    // re-post ( broadcast )
    [[NSNotificationCenter defaultCenter] postNotificationName:CDVLocalNotification object:notification];
}

- (NSUInteger)application:(UIApplication*)application supportedInterfaceOrientationsForWindow:(UIWindow*)window
{
    // iPhone doesn't support upside down by default, while the iPad does.  Override to allow all orientations always, and let the root view controller decide what's allowed (the supported orientations mask gets intersected).
    NSUInteger supportedInterfaceOrientations = (1 << UIInterfaceOrientationPortrait) | (1 << UIInterfaceOrientationLandscapeLeft) | (1 << UIInterfaceOrientationLandscapeRight) | (1 << UIInterfaceOrientationPortraitUpsideDown);

    return supportedInterfaceOrientations;
}

- (void)applicationDidReceiveMemoryWarning:(UIApplication*)application
{
    [[NSURLCache sharedURLCache] removeAllCachedResponses];
    NSLog(@"Cache Cleared");
}

CDVViewController.m

- (void)didReceiveMemoryWarning
{
    // iterate through all the plugin objects, and call hasPendingOperation
    // if at least one has a pending operation, we don't call [super didReceiveMemoryWarning]

    NSEnumerator* enumerator = [self.pluginObjects objectEnumerator];
    CDVPlugin* plugin;

    BOOL doPurge = YES;

    while ((plugin = [enumerator nextObject])) {
        if (plugin.hasPendingOperation) {
            NSLog(@"Plugin '%@' has a pending operation, memory purge is delayed for didReceiveMemoryWarning.", NSStringFromClass([plugin class]));
            doPurge = NO;
        }
    }

    if (doPurge) {
        // Releases the view if it doesn't have a superview.
        [super didReceiveMemoryWarning];
    }

    // Release any cached data, images, etc. that aren't in use.
}

- (void)viewDidUnload
{
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;

    self.webView.delegate = nil;
    self.webView = nil;
    [CDVUserAgentUtil releaseLock:&_userAgentLockToken];
}

#pragma mark UIWebViewDelegate

/**
 When web application loads Add stuff to the DOM, mainly the user-defined settings from the Settings.plist file, and
 the device's data such as device ID, platform version, etc.
 */
- (void)webViewDidStartLoad:(UIWebView*)theWebView
{
    NSLog(@"Resetting plugins due to page load.");
    [_commandQueue resetRequestId];
    [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPluginResetNotification object:self.webView]];
}

/**
 Called when the webview finishes loading.  This stops the activity view.
 */
- (void)webViewDidFinishLoad:(UIWebView*)theWebView
{
    NSLog(@"Finished load of: %@", theWebView.request.URL);
    // It's safe to release the lock even if this is just a sub-frame that's finished loading.
    [CDVUserAgentUtil releaseLock:&_userAgentLockToken];

    /*
     * Hide the Top Activity THROBBER in the Battery Bar
     */
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];

    [self processOpenUrl];

    [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPageDidLoadNotification object:self.webView]];
    
}

【问题讨论】:

  • 模拟器的内存比实际设备大得多。您是否尝试过通过 Instruments 运行它?
  • 是的,运行仪器,并寻找内存泄漏...泄漏图表上没有显示任何内容。
  • 内存问题不仅仅由泄漏引起 - 尝试确定正在使用和占用内存的内容。
  • 你试过重启 iPad 吗?您还可以使用工具并查看所有当前的内存使用情况(活动监视器)。
  • 是的,我已经重启了 iPad,没有影响。我相信是带有视频的应用程序导致了它,因为没有任何视频的应用程序可以正常工作。但是非常有气质……视频应用很多次都不行,然后我重新编译就可以了,但是iPad上的应用缓存一清空,又崩溃了。

标签: ios ipad memory-leaks


【解决方案1】:

我在使用 phonegap 时也遇到了我的应用程序的问题,但是一旦我们在应用程序委托中实施了此修复程序,一切都运行良好。在您的情况下,因为您说清空缓存不起作用,也许您只需要指定缓存大小,在这种情况下只需使用下面的 (BOOL) 应用程序代码。

在 appdelegate.m 中

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
     int cacheSizeMemory = 16*1024*1024; // 16MB
    int cacheSizeDisk = 32*1024*1024; // 32MB
    NSURLCache *sharedCache = [[[NSURLCache alloc] initWithMemoryCapacity:cacheSizeMemory diskCapacity:cacheSizeDisk diskPath:@"nsurlcache"] autorelease];
    [NSURLCache setSharedURLCache:sharedCache];
}
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
    [[NSURLCache sharedURLCache] removeAllCachedResponses];
    NSLog(@"Cache Cleared");
}

此外,我们在 CDVViewController.m 中使用了它以每 1 秒清除一次,

- (void)webViewDidFinishLoad:(UIWebView*)theWebView
{   //...
      [[NSURLCache sharedURLCache] removeAllCachedResponses];
        NSLog(@"Cache Cleared");

       [NSTimer scheduledTimerWithTimeInterval: 1.0
                                                      target: self
                                                    selector:@selector(onTick:)
                                      userInfo: nil repeats: YES];

    }

    -(void)onTick:(NSTimer *)timer {
        [[NSURLCache sharedURLCache] removeAllCachedResponses];
        NSLog(@"Cache Cleared");

    }

【讨论】:

  • 这似乎不起作用.. 第一段代码看起来有点工作但后来也失败了。我正在用我的文件中的内容更新我的问题。
  • 我们可以尝试两件事,删除你添加的内容 "int cacheSizeMemory = 16*1024*1024; // 16MB int cacheSizeDisk = 32*1024*1024; // 32MB NSURLCache *sharedCache = [[ [NSURLCache alloc] initWithMemoryCapacity:cacheSizeMemory diskCapacity:cacheSizeDisk diskPath:@"nsurlcache"] autorelease]; [NSURLCache setSharedURLCache:sharedCache];"然后加上这个看看缓存大小是多少 NSLog(@"Cache memory capacity = %d bytes", [[NSURLCache sharedURLCache] memoryCapacity]); NSLog(@"缓存磁盘容量 = %d 字节", [[NSURLCache sharedURLCache] diskCapacity]);
  • 另外看看这篇文章是否有帮助link
  • 当我用您提供的第二个代码替换第一个代码时...我应该看到什么?在哪里?
  • 抱歉的意思是把它加在这里 - (void)applicationDidReceiveMemoryWarning:(UIApplication*)application { } 然后当你的应用程序崩溃时它会给你字节,然后改变你的代码,例如我的在控制台中给了我这个信息,013-08-15 15:01:15.577 [514:907] 缓存已清除 2013-08-15 15:01:15.578 [514:907] 缓存容量 = 16777216 字节 2013-08- 15 15:01:15.579 [514:907] 缓存磁盘容量 = 33554432 字节所以我把它改成了这个,int cacheSizeMemory = 17*1024*1024; int cacheSizeDisk = 34*1024*1024;
猜你喜欢
  • 1970-01-01
  • 2015-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多