gpt4 book ai didi

ios - NSURLSessionDataTask 和线程

转载 作者:行者123 更新时间:2023-11-29 02:04:16 28 4
gpt4 key购买 nike

我使用 NSURLSessionDataTask 获取 JSON 提要,并填充位于共享存储(单例)内的 NSMutableArray。外部世界可以通过将其转换为 NSArray 的 getter 来访问 NSMutableArray。

getter 调用刷新方法,该方法轮询 JSON feed 并填充 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 时,提要都会刷新 7 次。我认为这与 getter 的 if 子句在 feed 下载时继续为 true 有关。我已经用 dispatch_once 缓解了这个问题,它有效,但我觉得这是不对的。

现在的代码是这样的:

- (NSMutableArray *)articles
{

if ([_articles count] == 0) {
static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{
[self refreshArticles];
});
}
return _articles;
}

但我的意思是:“如果没有文章,就去获取一些,然后然后返回”。有更好的方法吗?

最佳答案

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];
}

这里的关键要点:

  • 向用户显示一些“正在加载...”用户界面,而不是阻塞主线程。
  • 如果等效更新已在进行中,则不要触发其他更新。
  • 不要修改用于从后台线程填充 UI 的模型状态。

关于ios - NSURLSessionDataTask 和线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29972508/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com