用于iPad内存警告的Web App

时间:2013-08-15 15:49:42

标签: ios ipad memory-leaks

我正在开发一个使用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] Builtin   profile:container(sandbox)

     

8月15日11:50:12 BD-Graphics-Lab-6-iPad3   kernel [0]:launchd [4020]容器:   /私营/无功/移动/应用/ 997C5F22-C5A6-4A05-96C8-8ABEA9DAAC8A   (沙盒)

     

8月15日11:50:12 BD-Graphics-Lab-6-iPad3 BD Push   按钮[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.launchd 1   (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   ReportCrash [4021]:libMobileGestalt   copySystemVersionDictionaryValue:无法从中查找ReleaseType   系统版字典

     

8月15日11:50:17 BD-Graphics-Lab-6-iPad3   ReportCrash [4021]:保存的crashreport到   /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]];

}

LEAKS

ALLOCATIONS

enter image description here

1 个答案:

答案 0 :(得分:0)

我的应用程序也存在使用phonegap的问题,但是一旦我们在app delegate中实现了此修复程序,一切都运行良好。在您的情况下,因为您说清空缓存不起作用,可能您只需要指定缓存大小,在这种情况下只需使用下面的(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");

    }