发送到 iPhone 中已释放实例的消息

Posted

技术标签:

【中文标题】发送到 iPhone 中已释放实例的消息【英文标题】:Message sent to deallocated instance in iPhone 【发布时间】:2012-08-23 06:18:31 【问题描述】:

我是 iPhone 新手,

我正在按照苹果here 的建议创建 NSURLConnection 但是当我关闭我的视图时我的应用程序崩溃了,我尝试了NSZombieEnabled 的概念,它显示了-[CALayer release]: message sent to deallocated instance 0x68b8f40

我在Webview 中显示一个网页,当用户点击webview 中的下载链接时,shouldStartLoadWithRequest 方法将在此方法中被调用,我正在创建NSURLConnection

这是我的代码 sn-p,

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response

    [receivedData setLength:0];


- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data1

    [receivedData appendData:data1];


- (void)connectionDidFinishLoading:(NSURLConnection *)connection

    NSLog(@"Succeeded! Received %d bytes of data",[receivedData length]);

    DirPath=[self applicationDocumentsDirectory];

     NSLog(@"DirPath=%@",DirPath);
    [receivedData writeToFile:DirPath atomically:YES];

    UIAlertView* Alert = [[UIAlertView alloc] initWithTitle:@"Download Complete !"
                                                         message:nil delegate:nil 
                                               cancelButtonTitle:@"OK"
                                               otherButtonTitles:nil];
    [Alert show];
    [Alert release];


    // release the connection, and the data object
    [connection release];
    [receivedData release];



- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error1

    [connection release];
    [receivedData release];

    // inform the user
    NSLog(@"Connection failed! Error - %@ %@",
          [error1 localizedDescription],
          [[error1 userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);


- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType 


    //CAPTURE USER LINK-CLICK.

            Durl=[[url absoluteString]copy];

            //Checking for Duplicate .FILE at downloaded path....

            BOOL success =[[NSFileManager defaultManager] fileExistsAtPath:path];
            lastPath=[[url lastPathComponent] copy];

            if (success) //if duplicate file found...
            
                UIAlertView* Alert = [[UIAlertView alloc] initWithTitle:@"This FILE is already present in Library."
                                                                     message:@"Do you want to Downlaod again ?" delegate:self 
                                                           cancelButtonTitle:nil
                                                           otherButtonTitles:@"Yes",@"No",nil];
                [Alert show];
                [Alert release];

            
            else  //if duplicate file not found directly start download...
            
                // Create the request.
                NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:Durl]
                                                          cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                      timeoutInterval:60.0];

                // create the connection with the request and start loading the data
                NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
                if (theConnection) 
                    // Create the NSMutableData to hold the received data.
                    receivedData = [[NSMutableData data] retain];
                 else 
                    NSLog(@"Inform the user that the connection failed."); 
                

    return YES;   

我们将不胜感激。

【问题讨论】:

评论此行并检查[连接释放]; 已经试过了,但是不行。 你也评论了receivedData吗? 是的,我尝试了两种可能性,有评论和没有评论,但仍然崩溃。 NSLog(@" connection %p",connection); NSLog(@"receivedData %p",receivedData); NSLog(@"webView %p",webView);打印对象地址并检查是哪一个导致了崩溃。并且还在 connection 和 receivedData 对象上调用 retain。 【参考方案1】:

确保在您的 dealloc 实现中将 delegate 重置为 nil。另一个这样做的地方是viewWillDisappear:

您的应用程序崩溃/访问僵尸的原因是UIWebView 实例可能会尝试回调 viewController,即使它已经被释放。为了防止这种情况发生,您必须在 viewController 超出范围之前将 UIWebViewdelegate 设置回 nil。在 ios5 的 ARC 实现之前使用委托时,这是一个普遍的问题。 iOS5 最终提供了弱引用,这些实际上是 nil 本身,一旦它们的实例被释放。

示例 A:

- (void)dealloc

    [...]
    _webView.delegate = nil;

示例 B:

- (void)viewWillDisappaer:(BOOL)animated

    [super viewWillDisappaer:animated];
    _webView.delegate = nil;


编辑: 再次阅读您的问题后,我意识到僵尸是 UIView 或 UIControl,因为消息被发送到 CALayer。通过暂时删除所有与 webView 相关的代码,确保您的问题实际上与 web 视图有关。

【讨论】:

我不确定,但问题与webview无关,它与NSURLConnection连接导致崩溃有关。【参考方案2】:

我认为这个NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self]; 有问题

您正在创建一个带有委托自我的NSURLConnection 实例,当您关闭视图时,该视图上的所有内容都会得到deallocated。但是当NSURLConnection试图调用它的委托方法时会发生崩溃。

所以你需要在你的viewWillDisappear 中将NSURLConnection 的委托设置为nil,你需要在接口中创建NSURLConnection 的对象。

@interface yourClass

   NSURLConnection *theConnection;

@end

在.m

theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];

- (void)viewWillDisappaer:(BOOL)animated

    [super viewWillDisappaer:animated];
    theConnection.delegate = nil;

【讨论】:

以上是关于发送到 iPhone 中已释放实例的消息的主要内容,如果未能解决你的问题,请参考以下文章

-[CALayer retain]:消息发送到释放的实例

如何查找匹配对象:-[CFArray _cfTypeID]:发送到已释放实例的消息

NSError 释放:消息发送到释放的实例

ViewController respondsToSelector:]: 消息发送到释放的实例

发送到已释放实例问题的消息

[CustomViewController respondsToSelector:]:消息发送到释放的实例