我不是 ASIHTTPRequest 专家(NSURLRequest 一直做得很好),但是从快速查看代码来看,您似乎可以使用它的委托和 didFinishSelector 属性来告诉它何时 URL 请求是完成的。所以,例如:
- (void)startURLRequest
{
ASIHTTPRequest *myRequest;
/* code to set the request up with your target URL, etc here */
myRequest.delegate = self;
myRequest.didFinishSelector = @selector(HTTPRequestDidFinish:);
/* ... */
[myRequest startAsynchronous];
}
- (void)HTTPRequestDidFinish:(ASIHTTPRequest *)request
{
NSLog(@"Request %@ did finish, got data: %@", request, request.data);
[myTargetForData didReceiveData:request.data fromURL:request.originalURL];
}
Apple 明确建议您使用内置的 runloop 样式机制进行异步 HTTP 获取,而不是单独的线程。使用单独的线程可能会导致性能下降——至少在电池寿命和/或设备发热方面,即使它仍然足够快。
也就是说,作为一个学习点,到目前为止,将某些东西切换到单独的线程并将其报告回主线程(请记住:UIKit 对象可能仅从主线程发送消息)的最快方法是通过更改此:
- (void)postResult:(NSString *)result
{
instanceOfUILabel.text = result;
}
- (void)doExpensiveOperationOn:(NSString *)source
{
/* lots of expensive processing here, and then... */
[self postResult:result];
}
- (IBAction)userWantsOperationDone:(id)sender
{
[self doExpensiveOperationOn:@"some value or another"];
}
进入这个:
- (void)postResult:(NSString *)result
{
instanceOfUILabel.text = result;
}
- (void)doExpensiveOperationOn:(NSString *)source
{
/* we're on a thread without an autorelease pool now, probably we'll want one */
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
/* lots of expensive processing here, and then... */
/* in this simplified example, we assume that ownership of 'result' is here on this thread, possibly on the autorelease pool, so wait until postResult has definitely finished before doing anything that might release result */
[self performSelectorOnMainThread:@selector(postResult:) withObject:result waitUntilDone:YES];
[pool release];
}
- (IBAction)userWantsOperationDone:(id)sender
{
[self performSelectorOnBackgroundThread:@selector(doExpensiveOperationOn:) withObject:@"some value or another"];
}
尽管不考虑线程,但您可能会产生大约一百万个并发错误,在该示例中,一个明显的问题是触发 IBAction 的任何内容都可能 [可能] 在 doExpensiveOperationOn 完成之前再触发几次。多线程不是轻而易举的事情。