我试图在后台线程上发出网络请求,我决定使用 NSBlockOperations。我正在使用ADNKit来处理我的获取请求。这是代码:
- (void)reloadPosts
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
__block NSArray *additionalPosts;
__block ANKAPIResponseMeta *additionalMeta;
__block NSError *additionalError = nil;
NSBlockOperation *completionOperation = [NSBlockOperation blockOperationWithBlock:^{
PRSPostStreamDataController *strongSelf = weakSelf;
// update data or handle error
[strongSelf.data setPosts:additionalPosts withMeta:additionalMeta];
}];
NSBlockOperation *firstPostsOperation = [NSBlockOperation blockOperationWithBlock:^{
PRSPostStreamDataController *strongSelf = weakSelf;
NSDictionary *response = [strongSelf refreshPostsInPart:PartFirst];
firstPosts = [response objectForKey:@"posts"];
firstMeta = [response objectForKey:@"meta"];
firstError = [response objectForKey:@"error"];
}];
[completionOperation addDependency:firstPostsOperation];
[self.queue addOperation:firstPostsOperation];
[self.queue addOperation:completionOperation];
});
}
- (NSDictionary *)refreshPostsInPart:(StreamPart)part
{
// get pagination IDs from data object
ANKPaginationSettings *pagination = [[ANKPaginationSettings alloc] init];
pagination.beforeID = [data beforeIDForPart:part];
pagination.sinceID = [data sinceIDForPart:part];
pagination.count = 20;
// authenticatedClient is an object returned from a singleton managing accounts
ANKClient *client = [authenticatedClient clientWithPagination:pagination];
__block NSMutableArray *posts = [NSMutableArray new];
__block ANKAPIResponseMeta *m = nil;
__block BOOL isMore = YES;
__block NSError *err;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
__block NSString *originalMaxID;
while ((isMore) && (!err)) {
self.apiCallMaker(client, ^(id responseObject, ANKAPIResponseMeta *meta, NSError *error){
if (!error) {
if (!originalMaxID) {
originalMaxID = meta.maxID;
}
m = meta;
[posts addObjectsFromArray:(NSArray *)responseObject];
client.pagination.beforeID = meta.minID;
isMore = meta.moreDataAvailable;
} else {
err = error;
}
// signal that we are ready for the next iteration of the while loop
dispatch_semaphore_signal(semaphore);
});
// wait for the signal from the completion block
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}
if (!err) {
m.maxID = originalMaxID;
}
NSMutableDictionary *response = [NSMutableDictionary new];
if (posts) [response setObject:posts forKey:@"posts"];
if (m) [response setObject:m forKey:@"meta"];
if (err) [response setObject:err forKey:@"error"];
return response;
}
...
typedef void (^APIPostListCallback)(id responseObject, ANKAPIResponseMeta *meta, NSError *error);
- (void (^)(ANKClient *client, APIPostListCallback callback))apiCallMaker
{
return [^(ANKClient *client, APIPostListCallback callback) {
[client fetchPostsMentioningUser:self.user completion:callback];
} copy];
}
我的代码应该是自我解释的,但是当我调用 self.apiCallMaker 时,我引用的是配置对象中定义的属性。请参阅我之前提出的这个问题,以获取有关该属性发生了什么的更多详细信息
当我尝试获取超过 40 个帖子时,我无法保持界面不卡顿。我将数据划分为 1 - 5 个部分,每个部分可以包含 1 - 200 多个帖子。当然,如果可以的话,我会把这些剪掉。我的问题是,当我重新加载所有数据时,我会使用这些 NSBlockOperations 之一重新加载每个部分。我在这里只展示了一个,以使其尽可能简洁。我已经在仪器中对此进行了测试,每次 ANKClient 对象将其 JSON 响应转换为 ANKPost 对象时,我的 CPU 都固定在 100% 以上,并且我的界面卡顿了。
问题:
- 将 JSON 响应转换为由 ANKClient 的完成处理程序执行的 ANKPost 对象是否在主线程之外完成?
- 每个 NSBlockOperation 中的所有内容都是在主线程之外执行的吗?
- 一切都是在
refreshPostsInPart:
主线程之外执行的吗? - 我的数据对象的方法是
setPosts:withMeta:
在主线程之外执行的吗? - 如果我删除了该
dispatch_async
块,上述问题的任何答案都会改变吗?