当控制器被解除分配时,清理挂起的NSURLConnections

时间:2010-09-08 06:48:40

标签: iphone objective-c memory-management nsurlconnection nsurlrequest

我有一个控制器,它使用自定义类发出HTTP GET请求,该自定义类充当NSURLConnection的委托。一旦NSURLConnection失败或结束,自定义类就会调用控制器上的方法并传递接收数据的NSData对象。

我遇到了一个问题,即动态创建控制器并将其推送到导航控制器的堆栈。此控制器使用其viewDidLoad方法生成HTTP GET请求。如果用户快速按下导航栏上的“后退”,则该控制器将被解除分配。如果在HTTP GET请求完成之前发生这种情况,则生成的NSURLConnection回调将成为对dealloc'ed对象的方法调用,从而产生EXC_BAD_ACCESS。

清理已被实际可能已经解除分配的控制器启动的任何待处理NSURLConnections的最佳方法是什么?

我投入了一些NSLog语句,似乎我用作NSURLConnection委托的自定义类实际上并未收到dealloc消息。我确保在viewDidUnload中将该类的控制器实例设置为nil,并在其上调用release,但它看起来仍然比控制器长。

3 个答案:

答案 0 :(得分:2)

如果我理解正确,你只需要在viewDidUnload或dealloc方法中执行[whateverConnection cancel]。这取消了连接。如果您有一个自定义下载程序对象,例如对于使用NSURLConnection的某个大图像,则几乎相同。为您的类创建一个取消方法(取消连接并释放它),并在控制器的dealloc方法中调用它。您还应该使用类似于wasCanceled的bool标志,如果从cancel方法设置了wasCanceled,则不要从自定义对象的委托中调用任何方法。 (您只有一个指向您的委托的弱指针,因此当某个其他对象调用您的cancel方法时它可能已经释放)。我假设您的自定义对象的委托是视图控制器。我有几个像这样的下载程序,它工作正常,即使我很快取消了下载也没有泄漏。

@interface CompaniesDownloader : NSObject /*<NSXMLParserDelegate>*/
{
    id<CompaniesDownloaderDelegate> delegate; //a view controller is the delegate
    NSMutableArray *companies;

    BOOL isWorking;    
    BOOL wasCanceled;   

    @private

    //url connection object
    NSURLConnection *companiesConnection;

    //this is where i put the binary data that gets transformed into xml
    NSMutableData *webData;

    //temporary string used when parsing xml
    NSMutableString *tmpString;

    //temporary company used when parsing xml
    Company *tmpCompany;
}

在实施中:

-(void) cancel
{
  [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible: FALSE];

  wasCanceled = TRUE;
  [companiesConnection cancel];
  [webData release];
  webData = nil;
  self.companiesConnection = nil; //OR [companiesConnection release]; companiesConnection=nil;
  isWorking = FALSE;
}

答案 1 :(得分:0)

您需要在发出请求时保留视图控制器,并在get请求完成时释放

YourViewController.m
- (void)callGetRequest {
   [self retain];
}

- (void)didFinishAllGetTask {
   [self release];
}

答案 2 :(得分:0)

  

如果用户快速按下导航栏上的“后退”,则此控制器将被解除分配。如果在HTTP GET请求完成之前发生这种情况,则生成的NSURLConnection回调将成为对dealloc'ed对象的方法调用,从而产生EXC_BAD_ACCESS。

当用户点击后退按钮时,取消注册视图控制器类作为该对象的委托。 (保持对视图控制器类中对象的引用,这样您就可以执行someObject.delegate = nil;)之类的操作。您可以在视图控制器的dealloc方法中执行此操作。