3

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

我遇到了一个问题,即动态创建正在运行的控制器并将其推送到导航控制器的堆栈中。该控制器在其viewDidLoad方法中发出 HTTP GET 请求。如果用户在导航栏上快速按下“返回”,这个控制器就会被解除分配。如果这发生在 HTTP GET 请求完成之前,则结果NSURLConnection回调将成为对已释放对象的方法调用,从而导致 EXC_BAD_ACCESS。

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

我加入了一些NSLog声明,似乎我用作NSURLConnection委托的自定义类实际上并没有收到dealloc消息。我确保将此类的控制器实例设置为 nil in viewDidUnload,并对其调用 release ,但它似乎仍然比控制器寿命更长。

4

3 回答 3

2

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

@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;
}
于 2010-09-08T10:50:46.060 回答
0

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

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

- (void)didFinishAllGetTask {
   [self release];
}
于 2010-09-08T06:55:50.047 回答
0

如果用户在导航栏上快速按下“返回”,这个控制器就会被解除分配。如果这发生在 HTTP GET 请求完成之前,则生成的 NSURLConnection 回调将成为对已释放对象的方法调用,从而导致 EXC_BAD_ACCESS。

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

于 2010-09-08T07:13:04.483 回答