UIWebView 发布导致崩溃

Posted

技术标签:

【中文标题】UIWebView 发布导致崩溃【英文标题】:UIWebView release causes crash 【发布时间】:2012-03-19 18:25:30 【问题描述】:

我有一个 UIViewController 子类,它有一个 UIWebView。它将 Web 视图添加为视图的子视图,并在 dealloc 中释放它。以下是相关代码:

#import "MediaVC.h"

@implementation MediaVC
@synthesize file, repository, server, delegate;

- (void)viewDidLoad 
    [super viewDidLoad];


    webView = [[UIWebView alloc] initWithFrame:[[self view] bounds]];
    [webView setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
    [webView setScalesPageToFit:YES];
    [webView setMultipleTouchEnabled:YES];

    [[self view] addSubview:webView];

    [self displayFile];


    [flex release];
    [buttonDone release];
    [buttonAction release];



- (void)displayFile 

    if (!mimeString) 
        [webView loadData:nil 
                 MIMEType:nil 
         textEncodingName:nil 
                  baseURL:nil];


        [SVProgressHUD dismissWithError:@"Can't display this file." afterDelay:2];
     else 

        [[DataCenter sharedInstance] getDataForFile:file 
                                             server:server 
                                         repository:repository 
                                            isThumb:NO
                                         completion:^(NSData *data) 

                                             NSString *filenamePath =[NSString stringWithFormat:@"temp.%@", [[file path] pathExtension]];
                                             NSString *docDir = [DataCenter getDocumentsDirectoryPath];

                                             NSString *fullPath = [docDir stringByAppendingPathComponent:filenamePath];

                                             [data writeToFile:fullPath atomically:YES];

                                             [webView loadData:data 
                                                      MIMEType:[DataCenter mimeTypeForFile:file]
                                              textEncodingName:nil 
                                                       baseURL:nil];

                                             if (!data) 
                                                 [SVProgressHUD dismissWithError:@"Error!"];
                                              else 
                                                 [SVProgressHUD dismiss];
                                             

                                          progress:^(float progress) 
                                             [SVProgressHUD setFloat:progress];
                                         ];


    



- (void)dealloc 
    [buttonNext release];
    [buttonBack release];
    //[webView release]; ---CRASH HAPPENS IF I UNCOMMENT THIS LINE
    [super dealloc];


@end

应用程序在 [super dealloc] 处崩溃;。我有 NSZombieEnabled,它没有给我任何关于“发送到已释放实例的错误......”的错误。我确实发现,如果我注释掉[webView release],,就不会发生崩溃。 我检查了一下,我只分配一次 UIWebView 并释放一次。

更新请在下面找到完整的课程。正如我所说,那门课有很多不相关的东西,我找不到任何问题,也许你们找到了一些东西:

#import "MediaVC.h"
#import "DataCenter.h"
#import "SVProgressHUD.h"
#import "File.h"

@implementation MediaVC
@synthesize file, repository, server, delegate;

- (void)viewDidLoad 
    [super viewDidLoad];

    UIBarButtonItem *buttonDone = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone
                                                                                target:self 
                                                                                action:@selector(done)];

    UIBarButtonItem *buttonAction = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction
                                                                                  target:self 
                                                                                  action:@selector(action:)];


    buttonNext = [[UIBarButtonItem alloc] initWithTitle:@"Next" 
                                                  style:UIBarButtonItemStyleDone 
                                                 target:self 
                                                 action:@selector(next)];

    buttonBack = [[UIBarButtonItem alloc] initWithTitle:@"Back" 
                                                  style:UIBarButtonItemStyleDone 
                                                 target:self 
                                                 action:@selector(back)];

    UIBarButtonItem *flex = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace 
                                                                          target:nil 
                                                                          action:nil];


    [[self navigationItem] setLeftBarButtonItem:buttonDone];
    [[self navigationItem] setRightBarButtonItem:buttonAction];
    [[self navigationController] setToolbarHidden:NO];
    [self setToolbarItems:[NSArray arrayWithObjects:buttonBack, flex, buttonNext, nil] animated:YES];



    webView = [[UIWebView alloc] initWithFrame:[[self view] bounds]];
    [webView setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
    [webView setScalesPageToFit:YES];
    [webView setMultipleTouchEnabled:YES];

    [[self view] addSubview:webView];

    [self displayFile];


    [flex release];
    [buttonDone release];
    [buttonAction release];


- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 
    return YES;


- (void)done 
    [delegate doneMediaVC:self];


- (void)action:(id)button 
    NSString *filenamePath = [file path];
    NSString *docDir = [DataCenter getDocumentsDirectoryPath];

    NSString *fullPath = [docDir stringByAppendingPathComponent:filenamePath];

    NSURL *url = [NSURL fileURLWithPath:fullPath];
    UIDocumentInteractionController *c = [UIDocumentInteractionController interactionControllerWithURL:url];
    BOOL success = [c presentOpenInMenuFromBarButtonItem:buttonBack animated:YES];
    if (!success) 
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error" message:@"An application cannt be found to open this file" 
                                                           delegate:nil 
                                                  cancelButtonTitle:@"OK" 
                                                  otherButtonTitles:nil, nil];
        [alertView show];
        [alertView release];
    


- (void)displayFile 

    [self setTitle:[file name]];

    [SVProgressHUD showInView:[[self navigationController] view] 
                       status:@"Loading..." 
             networkIndicator:YES
                     progress:YES];

    NSString *mimeString = [DataCenter mimeTypeForFile:file];


    if (!mimeString) 
        [webView loadData:nil 
                 MIMEType:nil 
         textEncodingName:nil 
                  baseURL:nil];


        [SVProgressHUD dismissWithError:@"Can't display this file." afterDelay:2];
     else 

        [[DataCenter sharedInstance] getDataForFile:file 
                                             server:server 
                                         repository:repository 
                                            isThumb:NO
                                         completion:^(NSData *data) 

                                             NSString *filenamePath =[NSString stringWithFormat:@"temp.%@", [[file path] pathExtension]];
                                             NSString *docDir = [DataCenter getDocumentsDirectoryPath];

                                             NSString *fullPath = [docDir stringByAppendingPathComponent:filenamePath];

                                             [data writeToFile:fullPath atomically:YES];

                                             [webView loadData:data 
                                                      MIMEType:[DataCenter mimeTypeForFile:file]
                                              textEncodingName:nil 
                                                       baseURL:nil];

                                             if (!data) 
                                                 [SVProgressHUD dismissWithError:@"Error!"];
                                              else 
                                                 [SVProgressHUD dismiss];
                                             

                                          progress:^(float progress) 
                                             [SVProgressHUD setFloat:progress];
                                         ];


    

    if (![delegate canGoNext:self currentFile:file]) 
        [buttonNext setEnabled:NO];
     else 
        [buttonNext setEnabled:YES];
    


    if (![delegate canGoPrevious:self currentFile:file]) 
        [buttonBack setEnabled:NO];
     else 
        [buttonBack setEnabled:YES];
    


- (void)back 
    [self setFile:[delegate getPreviousFileForMediaVC:self currentFile:file]];
    [self displayFile];


- (void)next 
    [self setFile:[delegate getNextFileForMediaVC:self currentFile:file]];
    [self displayFile];


- (void)dealloc 
    [buttonNext release];
    [buttonBack release];
    //[webView release];
    [super dealloc];


@end

谢谢!

【问题讨论】:

webview变量的分配和释放没有问题。也许您创建了一个映射到 webview 的保留属性?如果不是,那么一定是其他原因导致了崩溃。 @PhilippeLeybaert 查看丢失的代码量,实际代码可能有很多错误。 我知道,这就是为什么我说变量的分配/释放没有问题,可能是其他原因导致了问题。 @PhilippeLeybaert 很好,因为您应该在释放 webview 变量之前将委托设置为 nil。 我刚刚在原始问题中粘贴了 amy complete class。 【参考方案1】:

您在文档中看到这一行了吗?

重要事项在发布您拥有的 UIWebView 实例之前 设置委托,您必须首先将其委托属性设置为 nil。这 例如,可以在您的 dealloc 方法中完成。

您的“相关代码”没有显示您设置委托,但话又说回来,您的相关代码根本不完整。 (flex?buttonDone?buttonAction?)

如果您想要一个好的答案,请分享所有代码。

【讨论】:

我刚刚在原始问题中粘贴了 amy complete class。

以上是关于UIWebView 发布导致崩溃的主要内容,如果未能解决你的问题,请参考以下文章

WebCore 的崩溃是不是意味着它必然与 UIWebView 相关?

UIWebView 应用程序因内存压力而崩溃

UIWebView iOS 5:WebKit/JavaScriptCore 崩溃

iOS 5 - 空白 UIWebView 在 ViewDidAppear 之前导致长时间延迟

iOS 9 UIWebview 嵌入式视频全屏播放导致约束错误

为啥在创建 UIWebView 后清除 NSUserDefaults 会导致 EXC_CRASH?