我有一个控制器,它使用自定义类发出HTTP GET请求,该自定义类充当NSURLConnection
的委托。一旦NSURLConnection
失败或结束,自定义类就会调用控制器上的方法并传递接收数据的NSData
对象。
我遇到了一个问题,即动态创建控制器并将其推送到导航控制器的堆栈。此控制器使用其viewDidLoad
方法生成HTTP GET请求。如果用户快速按下导航栏上的“后退”,则该控制器将被解除分配。如果在HTTP GET请求完成之前发生这种情况,则生成的NSURLConnection
回调将成为对dealloc'ed对象的方法调用,从而产生EXC_BAD_ACCESS。
清理已被实际可能已经解除分配的控制器启动的任何待处理NSURLConnections
的最佳方法是什么?
我投入了一些NSLog
语句,似乎我用作NSURLConnection
委托的自定义类实际上并未收到dealloc
消息。我确保在viewDidUnload
中将该类的控制器实例设置为nil,并在其上调用release,但它看起来仍然比控制器长。
答案 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
方法中执行此操作。