我遇到了内存泄漏,但无法通过泄漏、构建/分析或整体检查来找出如何修复。我有一个非常强烈的想法,这是由于我的 UIWebview 加载 JavaScript 的 loadRequest 命令造成的,但我不知道出了什么问题。
这是我的设置:
我有一个 tabbarcontroller,我以编程方式创建了 4 个视图控制器:分别是一个表视图、一个地图视图、另一个表视图和一个 Web 视图。
- 第一个表格视图显示静态数据。
- 地图视图显示注释,单击该注释会填充第四个选项卡(即 Web 视图)的变量,并切换到 Web 视图以显示本地存储的 html/javascript 文件(即 3D 模型)
- 第二个表格视图列出了地图视图中每个注释所代表的所有相同信息,只是以表格形式呈现。它在填充变量、在 web 视图中切换和显示 html/javascript 文件方面具有相同的功能
- webview 显示加载的 html/javascript 文件,如果没有,它显示一个 UIAlertView 以从地图视图或列表中选择一个
当我最终从 webview 执行 loadRequest() 时,最初一切正常。但是,当我开始在选项卡之间切换并查看不同的 3D 模型时(即,转到地图视图,单击注释以显示模型 x,观察它在 Web 视图中加载,然后切换到列表并单击一行以显示模型) y(或 x )并观察它在 web 视图中加载)我开始在 ipad 上收到内存泄漏,而不是模拟器。这些内存泄漏几乎总是:常规块 56、1024、8、244 和 24,并且没有负责的帧、库或堆栈跟踪可供跟踪。
在网络视图中,如果我注释掉 loadrequest 行或使用 request object = nil 执行 loadrequest,我没有内存泄漏,但是当我切换到使用指向本地文件的 url 对象时(我什至尝试将其指向 google) .com,其中有 javascript)它会爆发内存泄漏。
我尝试过执行以下每一项操作:
- [self.webView loadRequest:nil];
- [self.webView loadHTMLString:@"" baseURL:nil];
- [self.webView停止加载];
在我的 webViewController 的 viewWillDisappear 中,试图完全清除 webview 以供将来重用,但它似乎没有多大帮助。我也尝试在执行 loadRequest 之前执行此操作,但我遇到了相同的内存泄漏。
- 仅供参考,我正在运行最新的 xcode 4.0.2,ipad 有最新的更新,4.3.2
- 在上一篇文章中我评论过但没有收到回复(一般块内存泄漏 https://stackoverflow.com/questions/5470121/generalblock-56-memory-leak-when-calling-loadrequest-in-uiwebview/5736448#5736448)我相信问题与以下事实有关:当我切换视图时,webview 不知道如何完全摆脱 JavaScript
- 我用一个没有 javascript 的简单 html 文件做了一个测试,一般块内存泄漏消失了。但是,我收到其他 cfnetwork / http 消息内存泄漏,但这是一个不同的故事,目前不是我关心的问题。
下面是单击 mapView 上的注释之一时触发 webViewController 中的 loadModel 函数的示例代码:
- (void) mapCallOutPressed: (UIView *) sender {
NSInteger selectedIndex = sender.tag;
MyLocation *selectedObject = [_mapView.annotations objectAtIndex:selectedIndex];
MyModel *model = selectedObject.model;
NSLog(@"Model selected from mapview = %@", model.description);
// Get reference to the webview from the tabBarController (viewController's index=3)
WebViewController *webViewController = [self.tabBarController.viewControllers objectAtIndex:3];
webViewController.model = model;
[webViewController loadModel];
// Switch tabs to the webView
self.tabBarController.selectedIndex = 3;
[self.tabBarController.selectedViewController viewDidAppear:YES];
下面是我的 webViewController.h 和 .m:
WebViewController.h:
WebViewController : UIViewController <UIWebViewDelegate> {
UIWebView *webView;
NSString *templateRunFilePath;
MyModel *model;
NSString *templateRunTitle;
@property (nonatomic, retain) UIWebView *webView;
@property (assign) MyModel *model;
@property (nonatomic, copy) NSString *templateRunFilePath;
@property (nonatomic, copy) NSString *templateRunTitle;
-(void) loadModel;
WebViewController.m:
- (void) viewDidLoad {
[super viewDidLoad];
NSLog(@"in webview did load");
self.webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)];
self.webView.delegate = self;
self.webView.autoresizingMask=(UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth);
self.webView.scalesPageToFit = YES;
[self.view addSubview:self.webView];
}
- (void) viewWillAppear:(BOOL)animated {
if (self.model) {
self.tabBarController.navigationItem.title = [NSString stringWithFormat: @"%@ - %@", self.tabBarController.navigationItem.title, self.model.description];
}
else {
UIAlertView *msg = [[UIAlertView alloc] initWithTitle:@"No Model Selected"
message:@"Please select a model from the map or list tab to view."
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[msg show];
[msg release];
}
}
- (void) loadModel {
NSString *localURLPath = [NSString stringWithFormat:@"%@/%@/%@", self.templateRunFilePath, self.model.folderName, self.model.modelFileName];
NSURL *url = [NSURL fileURLWithPath:localURLPath];
NSURLRequest *requestObj = [NSURLRequest requestWithURL: url];
[self.webView loadRequest:requestObj];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
[[NSUserDefaults standardUserDefaults] setInteger:0 forKey:@"WebKitCacheModelPreferenceKey"];
}
-(void)viewWillDisappear:(BOOL)animated {
NSLog(@"webview view will disappear");
[super viewWillDisappear:animated];
//[self.webView loadRequest:nil];
//[self.webView loadHTMLString:@"" baseURL:nil];
self.webView.delegate = nil;
}
- (void)dealloc {
self.webView.delegate = nil;
[self.webView release];
[super dealloc];
}
如果您有任何建议或更正,我将不胜感激。我有不到 1 周的时间来解决这个问题,如果您能给我任何见解,我将非常感谢。
thanks!
-Mike