我希望以异步方式向服务器接收一些数据,并避免重载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)
....
}
这是对的吗?或者还有其他方法可以解决这个问题吗?
答案 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接口。更好的方法是在应用程序和服务器之间打开持久套接字,然后您可以随意上下推送数据。带有心跳的插槽也会在连接断开时通知您。不确定您是否希望我再详细说明这个选项......