我正在使用NSURLSessionDataTask获取JSON提要并填充位于共享存储区内的NSMutableArray,该存储区是一个单例。外部世界可以通过将其强制转换为NSArray的getter访问NSMutableArray。
getter调用一个刷新方法,该方法轮询JSON提要并填充NSMutableArray,如下所示:
- (NSArray *)articles
{
if ([_articles count] == 0) {
[self refreshArticles];
}
return _articles;
}
以下是一些方法:
NSURLRequest *request = [NSURLRequest requestWithURL:feedURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:4.0];
NSURLSessionDataTask *task = [self.session dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){
if (!error && response != nil) {
// decode JSON and add resultant objects to _articles
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"Updated feed");
[nc postNotificationName:@"MLNArticleStoreFeedDidUpdate" object:self];
});
} else if (response == nil) {
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc postNotificationName:@"MLNNetworkError" object:self];
}
}];
[task resume];
这样可行,但每次调用getter时,Feed都会刷新7次。我认为这与getter的if子句在Feed下载时继续为真。我用dispatch_once
缓解了这个问题,但它确实有效,但我觉得这样做不对。
以下是代码的内容:
- (NSMutableArray *)articles
{
if ([_articles count] == 0) {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self refreshArticles];
});
}
return _articles;
}
但我意味着是:"如果没有文章,请去获取一些, 然后 返回" 。有没有更好的方法呢?
答案 0 :(得分:1)
dispatch_once
将不会执行您要执行的操作。这里真实的是你几乎肯定不想要在返回之前等待网络活动。如果您阻止这样的主线程,操作系统将终止您的应用程序。
- (NSArray *)articles
{
if ([_articles count] == 0) {
[self refreshArticlesFromNetwork];
}
return _articles;
}
- (void)refreshArticlesFromNetwork
{
if (self.networkRefreshInProgress)
return;
self.networkRefreshInProgress = YES;
[self showNetworkLoadingUI];
NSURLRequest *request = [NSURLRequest requestWithURL:feedURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:4.0];
NSURLSessionDataTask *task = [self.session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){
NSMutableArray* localArray = [NSMutableArray array];
if (!error && response != nil) {
// decode JSON and add resultant objects to local array
[localArray addObject: ... ];
}
dispatch_async(dispatch_get_main_queue(), ^{
_articles = [localArray copy];
self.networkRefreshInProgress = NO;
[self hideNetworkLoadingUI];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
if (!error && response != nil) {
[nc postNotificationName:@"MLNArticleStoreFeedDidUpdate" object:self];
} else if (response == nil) {
[nc postNotificationName:@"MLNNetworkError" object:self];
}
NSLog(@"Updated feed");
});
}];
[task resume];
}
这里的关键要点: