我想在后台线程上的 NSOperation 内部执行异步 NSURLConnection 。
这是因为当数据返回时我正在对数据进行一些非常昂贵的操作。
这与他们在这里提出的问题非常相似:如何在 NSOperation 中执行异步 NSURLConnection?
但不同之处在于我在另一个类中运行连接。
这是我的第一次尝试:
在我的 MainViewController 中:
@property (nonatomic, strong) NSOperationQueue *requestQueue;
#pragma mark - Lazy initialization
- (NSOperationQueue *)requestQueue
{
if (!_requestQueue) {
_requestQueue = [[NSOperationQueue alloc] init];
_requestQueue.name = @"Request Start Application Queue";
_requestQueue.maxConcurrentOperationCount = 1;
}
return _requestQueue;
}
-(void)callToServer
{
URLJsonRequest *request = [URLRequestFactory createRequest:REQUEST_INTERFACE_CLIENT_VERSION
delegate:self];
RequestSender *requestSender = [[RequestSender alloc]initWithPhotoRecord:request delegate:self];
[self.requestQueue addOperation:requestSender];
}
这是我的操作:
- (id)initWithPhotoRecord:(URLJsonRequest *)request
delegate:(id<RequestSenderDelegate>) theDelegate{
if (self = [super init])
{
self.delegate = theDelegate;
self.jsonRequest = request;
}
return self;
}
- (void)main {
//Apple recommends using @autoreleasepool block instead of alloc and init NSAutoreleasePool, because blocks are more efficient. You might use NSAuoreleasePool instead and that would be fine.
@autoreleasepool
{
if (self.isCancelled)
return;
[self.jsonRequest start];
}
}
这是我的请求启动功能:
-(void) start
{
NSURL *url = [NSURL URLWithString:@"http://google.com"];
NSURLRequest *theRequest = [NSURLRequest requestWithURL:url];
urlConnection = [[[NSURLConnection alloc] initWithRequest:theRequest delegate:self]autorelease];
[urlConnection start];
[theRequest release]
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
NSLog(@"Received reponse from connection");
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection{
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
}
我没有收到服务器的响应。
几种方法:
-
安排NSURLConnection
在主运行循环中,通过使用startImmediately
的参数NO
,设置运行循环,然后才可以启动连接,例如:
urlConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self startImmediately:NO];
[urlConnection scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
[urlConnection start];
为该连接创建一个专用线程,并在为该线程创建的运行循环中安排该连接。看AFURLConnectionOperation.m
in AF网络一个例子的来源。
实际使用AF网络,这给了你NSOperation
您可以将其添加到队列中,并为您处理运行循环的操作。
因此,AFNetworking 会执行以下操作:
+ (void)networkRequestThreadEntryPoint:(id)__unused object {
@autoreleasepool {
[[NSThread currentThread] setName:@"NetworkingThread"];
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
[runLoop run];
}
}
+ (NSThread *)networkRequestThread {
static NSThread *_networkRequestThread = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
_networkRequestThread = [[NSThread alloc] initWithTarget:self
selector:@selector(networkRequestThreadEntryPoint:)
object:nil];
[_networkRequestThread start];
});
return _networkRequestThread;
}
所以我做了如下的事情。首先我有一些私有属性:
@property (nonatomic, readwrite, getter = isExecuting) BOOL executing;
@property (nonatomic, readwrite, getter = isFinished) BOOL finished;
@property (nonatomic, weak) NSURLConnection *connection;
然后网络操作可以执行如下操作:
@synthesize executing = _executing;
@synthesize finished = _finished;
- (instancetype)init {
self = [super init];
if (self) {
_executing = NO;
_finished = NO;
}
return self;
}
- (void)start {
if (self.isCancelled) {
[self completeOperation];
return;
}
self.executing = YES;
[self performSelector:@selector(startInNetworkRequestThread)
onThread:[[self class] networkRequestThread]
withObject:nil
waitUntilDone:NO];
}
- (void)startInNetworkRequestThread {
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:self.request
delegate:self
startImmediately:NO];
[connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
[connection start];
self.connection = connection;
}
- (void)completeOperation {
self.executing = NO;
self.finished = YES;
}
- (void)setFinished:(BOOL)finished {
if (finished != _finished) {
[self willChangeValueForKey:@"isFinished"];
_finished = finished;
[self didChangeValueForKey:@"isFinished"];
}
}
- (void)setExecuting:(BOOL)executing {
if (executing != _executing) {
[self willChangeValueForKey:@"isExecuting"];
_executing = executing;
[self didChangeValueForKey:@"isExecuting"];
}
}
- (BOOL)isConcurrent {
return YES;
}
- (BOOL)isAsynchronous {
return YES;
}
// all of my NSURLConnectionDataDelegate stuff here, for example, upon completion:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
// I call the appropriate completion blocks here, do cleanup, etc. and then, when done:
[self completeOperation];
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)