Ios 是否在主线程上调用NSURLSessionDataTask完成块?

Ios 是否在主线程上调用NSURLSessionDataTask完成块?,ios,objective-c,multithreading,Ios,Objective C,Multithreading,我一直在试图弄清楚什么时候可以“只输入我需要做的”,什么时候我需要具体说明我在什么样的线程上做什么样的工作 据我所知,我应该只更新主线程上的UI。这是否意味着这样做是不好的?我应该把这个放到GDC电话里吗 [sessionManager dataTaskWithRequest:aRequest completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullab

我一直在试图弄清楚什么时候可以“只输入我需要做的”,什么时候我需要具体说明我在什么样的线程上做什么样的工作

据我所知,我应该只更新主线程上的UI。这是否意味着这样做是不好的?我应该把这个放到GDC电话里吗

[sessionManager dataTaskWithRequest:aRequest completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error) {

    someUILabel.text = @"Hello!"; // Updating my UI
    [someTableView reloadData]; // Ask a table view to reload data

}];
这就是UI部分。现在,假设我的类中有一个
NSMutableArray
。我将通过点击
ui按钮
向该数组添加或删除对象。然后我又有一个
NSURLSessionDataTask
去某个服务器获取一些数据并将其加载到我的
NSMutableArray
,如下所示:

[sessionManager dataTaskWithRequest:aRequest completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error) {

    myMutableArray = [[responseObject objectForKey:@"results"] mutableCopy];

}];
这不是一个UI操作。当完成块运行时,是否需要将其包装在GDC调用中,以避免在我的按钮点击添加对象(即
[myMutableArray insertObject:someObj atIndex:4];
)之间的竞争条件下崩溃,还是设计为不会相互冲突


我省略了所有的错误处理来关注手头的问题。

TLDR:在完成处理程序中调用
dispatch\u async(dispatch\u get\u main\u queue()…
,无需花费任何费用,所以只需执行即可

长答案

让我们看一下文件,好吗

completionHandler
加载请求完成时要调用的完成处理程序。此处理程序在委托队列上执行

委托队列是您在使用
sessionWithConfiguration:delegateQueue:
创建NSURLSession时传入的队列。如果您不是这样创建此NSURLSession的,那么我建议您不要对调用完成处理程序的队列做任何假设。如果您没有通过
[NSOperationQueue mainQueue]
作为此参数,您处于后台队列中,在执行任何非线程安全的操作之前,应先进入主队列

所以现在的问题是:

  • 更新UI并与表视图对话是否是线程安全的?否,必须仅在主队列上执行这些操作

  • 设置
    myMutableArray
    是否对线程安全?否,因为您将在两个线程之间共享一个属性
    self.myMutableArray
    (主队列,您通常在其中与此属性对话,以及此队列,无论它是什么)


TLDR:在完成处理程序中调用
dispatch\u async(dispatch\u get\u main\u queue()…
,无需任何费用,所以只需执行即可

长答案

让我们看一下文件,好吗

completionHandler
加载请求完成时要调用的完成处理程序。此处理程序在委托队列上执行

委托队列是您在使用
sessionWithConfiguration:delegateQueue:
创建NSURLSession时传入的队列。如果您不是这样创建此NSURLSession的,那么我建议您不要对调用完成处理程序的队列做任何假设。如果您没有通过
[NSOperationQueue mainQueue]
作为此参数,您处于后台队列中,在执行任何非线程安全的操作之前,应先进入主队列

所以现在的问题是:

  • 更新UI并与表视图对话是否是线程安全的?否,必须仅在主队列上执行这些操作

  • 设置
    myMutableArray
    是否对线程安全?否,因为您将在两个线程之间共享一个属性
    self.myMutableArray
    (主队列,您通常在其中与此属性对话,以及此队列,无论它是什么)


“那就去做吧”:我当然可以,但是我会在各种地方插入调度,而不确定它是否真的有必要,甚至没有意义。我很清楚这是解决手头问题的一个方法,但我正在努力理解这个问题。但是谢谢你的解释。我看了一下文档,试图教育你我自己更进一步。我使用的是AFNetworking,而且它似乎默认在主线程上运行completionBlocks,除非另有规定,所以我想我不需要做任何事情。你不可能知道ofc。当然,很公平。我希望我们已经解决了问题的两个方面,即这是什么线程,这些是mo吗ves thread-safe.Yes,谢谢。只是为了确保我没有误解:假设AFNetworking在主线程上运行completionBlocks,那么直接访问属性(myMutableArray)是可以的在该块中,由于它随后被同一个线程访问,该线程响应假设的UIButton事件,该事件将同时修改数组?换句话说,它不会同时进行。绝对。主线程只是:一个线程。它是严格顺序的。来自这些完成处理程序之一的代码不能开始运行,直到所有其他代码都完成,反之亦然。两件事“同时发生”是没有危险的。这也是我理解的。很好。非常感谢!“所以就这么做吧”:我当然可以,但是我会在各种地方插入调度,而不确定它是否真的有必要,甚至没有意义。我很清楚这是解决手头问题的一个方法,但我正在努力理解这个问题。但是谢谢你的解释。我看了一下文档,试图教育你我自己更进一步。我使用的是AFNetworking,它似乎默认在主线程上运行completionBlocks,除非另有规定,所以我不需要做任何事情,我想。你不可能知道ofc。当然,公平。我希望我们之间已经解决了