更改视图时 ASIHTTPRequest 异步崩溃
Posted
技术标签:
【中文标题】更改视图时 ASIHTTPRequest 异步崩溃【英文标题】:ASIHTTPRequest Asynchronous Crash When Changing Views 【发布时间】:2011-06-10 13:35:53 【问题描述】:我正在使用 ASIHttpRequest 从 xml 文件中接收数据。但是,在异步请求期间,只要我更改视图(使用导航控制器返回上一个视图),应用程序就会崩溃,并在 main.m 上显示 EXC_BAD_ACCESS
这只发生在发出请求时。
下面是我的代码:
-(void)ProcessXML
//Set url from string to url
NSURL *theurl = [NSURL URLWithString:@"http://twitter.com/statuses/user_timeline/2smssupport.xml"];
asirequest = [ASIHTTPRequest requestWithURL:theurl];
[asirequest setDelegate:self];
[asirequest startAsynchronous];
- (void)requestFinished:(ASIHTTPRequest *)request
NSLog(@"Saving to Defaults");
NSData *responseData = [request responseData];
xmlSaved = responseData;
prefs = [NSUserDefaults standardUserDefaults];
[prefs setObject:responseData forKey:@"xmlDownload"];
rssParser = [[RssParser alloc] loadXMLbyURL:xmlSaved];
[self.tableView reloadData];
NSLog(@"%@",[prefs dataForKey:@"xmlDownload"]);
Process XML 方法触发请求,然后接收到的数据在 RequestFinished 中处理。
ASIHTTPRequest 一定有我遗漏的东西,但我不知道它是什么?
谢谢
【问题讨论】:
【参考方案1】:这段代码应该可以修复它:
-(void) viewWillDisappear:(BOOL)animated
[super viewWillDisappear:animated];
[request clearDelegatesAndCancel]
【讨论】:
【参考方案2】:如果视图正在释放,那么您在请求中设置的委托现在无效。确保在视图 dealloc 上将委托设置为 nil 并停止请求。
【讨论】:
我该怎么做?我已在 dealloc 中将 asirequest 设置为 nil,但它仍然崩溃 [asirequest setDelegate:nil]; 我收回了它,它确实有效......但现在它在 asihttprequest 类的某处出现 EXC_BAD_ACCESS 错误 开启僵尸 - 在可执行参数中将 NSZombieEnabled 添加为 YES 并查看它中断的行,它将显示正在过度释放的对象...【参考方案3】:asirequest
对象没有被保留在任何地方,所以它在ProcessXML
返回后被释放。
【讨论】:
即使视图改变了?请求发生在看起来是后台线程的地方。 它是自保留的,你不需要保留或释放它。 @Simon Lee,你为什么这么说?我刚刚检查了文档和源代码,我觉得它不像。 我的意思是请求是在主线程上发出的,但一切都在后台工作。这一直难倒我,所以我通常只使用同步请求。我现在收到以下错误:尝试使用不在框架中的块创建 USE_BLOCK_IN_FRAME 变量。 ||在 dealloc 中分配 [asirequest setDelegate:nil] 会导致应用立即崩溃 - (IBAction)grabURLInBackground:(id)sender NSURL *url = [NSURL URLWithString:@"allseeing-i.com"]; ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; [request setDelegate:self] ; [请求启动异步]; 【参考方案4】:NSZombieEnabled 对你有很大帮助。您可以判断是哪个对象导致了 EXC_BAD_ACCESS。
【讨论】:
【参考方案5】:您是否在离开当前视图时释放ASIHTTPRequest
对象?我的猜测是在您的视图控制器被释放后调用委托方法。
--
@Simon 是正确的,您确实需要将委托设置为 nil。我会做的是:
-
在您的类中创建一个
ASIHTTPRequest
属性并在您的ProcessXML
方法中设置该属性。这简化了内存管理并确保请求对象在您需要时始终存在。
在您的dealloc
方法和requestFinished
方法中,将请求委托设置为nil 并设置self.request = nil;
至少,您应该在 requestFinished
方法中将委托设置为 nil,但是如果您在返回之前离开此视图控制器,则需要记住停止运行您的请求,因此将其设置为 nil在dealloc
方法中也是如此。
【讨论】:
这可能是正确的,那么我将如何解决这个问题呢? iPhone 上的内存分配让我有些困惑 它是自保留的,你不需要保留或释放它。但根据我的回答,您需要将委托设置为 nil。 那我需要在哪里将代理设置为零?在交易中? @Simon - 更常见的术语是“自动发布”。当自动释放池在当前运行循环结束时耗尽时,它被标记为释放。 “自我保持”意味着它可以在任意时间内保持自己的存在,而它不能。 我可以随时调用 [self retain] 然后 [self release]。我很清楚自动发布...查看我的简历 ;)以上是关于更改视图时 ASIHTTPRequest 异步崩溃的主要内容,如果未能解决你的问题,请参考以下文章
iPhone ASIHTTPRequest 从 requestFinished 方法中异步提取响应