iOS:NSOperationQueue:辅助队列

时间:2014-02-24 10:05:43

标签: ios multithreading nsoperation nsoperationqueue

我希望以异步方式向服务器接收一些数据,并避免重载App UI performance。因此,希望将任务发送到辅助队列而不是主要队列。

这是我目前的解决方案,它使用“主队列” [NSOperationQueue mainQueue] ,据我所知,这会降低性能):

-(NSDictionary*) fetchURL:(NSString*)url
{
    NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:kCONTACTSINFOURL]];

    __block BOOL hasError = FALSE;
    __block NSDictionary *json;

    [NSURLConnection sendAsynchronousRequest:request
                                       queue:[NSOperationQueue mainQueue] 
                           completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError)
                           {
                               //Verify type of connection error

                               json = [NSJSONSerialization JSONObjectWithData:data
                                                                      options:0
                                                                        error:nil];
                               NSLog(@"Async JSON: %@", json);



                           }];

    if (hasError) {
        [[NSOperationQueue mainQueue] suspend];
        return nil;
    }
    return json;
}

为了使用辅助队列,并避免超载UI和App性能,是否可以分配共享的NSOperationQueue并参考?或是否有其他“更好”的类或方法实现这个?

这将是我使用辅助NSOperationQueue的改进解决方案:

创建辅助队列:

    NSOperationQueue* otherQueue = [NSOperationQueue init];

使用其他(辅助)队列:

....
[NSURLConnection sendAsynchronousRequest:request
                                       queue:otherQueue
                           completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError)
....

}

这是对的吗?或者还有其他方法可以解决这个问题吗?

1 个答案:

答案 0 :(得分:0)

...继续发表评论......

NSURLConnection方法

[NSURLConnection sendAsynchronousRequest:queue:completionHandler:]

允许您指定在连接完成时将调用完成处理程序的队列。如果您暂停此队列,您将不会停止发送请求,您将在完成后停止获取回调。您可能想要以稍微不同的方式考虑这个......

NSOperation很棒,但是我倾向于直接选择GCD(NSOperation只是一个很好的obj-c包装在顶部)如果你很难使用NSOperations让我知道,我会添加一些建议这一点。

我假设您有某种管理器类来处理所有服务器通信?如果没有,我会建议您这样做,并将其作为单身人士。

@ interface ChatManager : NSObject
    + (ChatManager *)sharedManager;
@end

@implementation ChatManager {
    dispatch_queue_t fetchQueue;
    dispatch_queue_t postQueue;
}
+ (ChatManager *)sharedManager {
    // This is just the standard apple pattern for creating a singleton
    static SCAddressBookManager *sharedManager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedManager = [[SCAddressBookManager alloc] init];
    });
    return sharedManager;
}

- (id)init {
    self = [super init];
    if (self) {
        // Create a dispatch queue that will run requests one after another, you could make this concurrent but that may cause messages to be lost when you suspend
        fetchQueue = dispatch_queue_create("fetch_queue", DISPATCH_QUEUE_SERIAL);
        postQueue = dispatch_queue_create("post_queue", DISPATCH_QUEUE_SERIAL);
    }
}

- (NSDictionary *)fetchURL:(NSURL *)url {
    // In here we will dispatch to our queue and so that the 
    dispatch_async(fetchQueue, ^{
        NSURLRequest = // create your request
        NSURLResponse *response = nil;
        NSError *error = nil;
        NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
        // Check for error
        if (error) dispatch_suspend(fetchQueue); // this suspends the queue that is making the calls to the server, so will stop attempting to send messages when you have an error - you should start pinging to see when you come back online here too, and then use dispatch_resume(fetchQueue) to get it going again!
        else {
            json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
            NSLog(@"Async JSON: %@", json);
            return json; // ??
        }
    });
}

- (NSDictionary *)postURL:(NSURL *)url data:(NSData *)bodyData {
    // In here we will dispatch to our queue and so that the 
    dispatch_async(postQueue, ^{
        /*
          Make your post request.
        */
        // Check for error
        if (error) dispatch_suspend(postQueue);
        else {
            json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
            NSLog(@"Async JSON: %@", json);
            return json; // ??
        }
    });
}

@end

您可能还需要使用

dispatch_sync(dispatch_get_main_queue(), ^{
    // Do stuff on the main thread here
};

如果你需要对主线程进行委托样式回调!

这是一个基本的想法,我将如何设置以尝试实现您的目标......如果对您没有任何意义,请随时告诉我。?

作为旁注,我假设无论出于何种原因,您需要为您的服务器提供简单的http接口。更好的方法是在应用程序和服务器之间打开持久套接字,然后您可以随意上下推送数据。带有心跳的插槽也会在连接断开时通知您。不确定您是否希望我再详细说明这个选项......