Ios uikit方法是否保证在主线程上运行?

Ios uikit方法是否保证在主线程上运行?,ios,objective-c,grand-central-dispatch,Ios,Objective C,Grand Central Dispatch,任何与UI相关的工作都需要在iOS的主线程上运行。有时我们需要做一些异步工作,比如下载图像,我们可能会使用dispatch_async,下载完成后,我们会得到主线程,并像这样显示它: dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ UIImage *overlayImage = [self faceOverlayImageFromImage:_image]; dispatch_async(

任何与UI相关的工作都需要在iOS的主线程上运行。有时我们需要做一些异步工作,比如下载图像,我们可能会使用dispatch_async,下载完成后,我们会得到主线程,并像这样显示它:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
UIImage *overlayImage = [self faceOverlayImageFromImage:_image];
dispatch_async(dispatch_get_main_queue(), ^{
    [self fadeInNewImage:overlayImage];
});
DispatchQueue.global(qos: .userInitiated).async { [weak self] in
    //This code will be on a background thread
    //Do time-consuming work here

    //This calls back to the main thread.
    DispatchQueue.main.async { [weak self] in
        //Put your code to display your results in the UI here.
    }
}
})}

但是,当我们在本地加载图像时,通常不在主线程上进行调度:

UIImageView *imageView = [[UIImageView alloc] initWithImage:@"myimage.png"];

我的问题是它们是否保证在主线程上运行?如果是,为什么要使用dispatch_get_main_queue()调度它?如果没有,为什么我们不在主线程上分派所有与ui相关的工作呢?

大多数与ui相关的操作都需要在主线程上执行,才能正常工作。但是仅仅使用
UI…
类本身并不能确保它在主线程上运行

这是你作为程序员的工作。如果您在后台执行某些操作(如下载数据或执行长时间运行的任务),然后需要更新UI,则必须确保UI代码在主线程上完成

请记住,可以在后台线程上安全地创建
UIImage
实例。那很安全


tl;dr-否,不保证在主线程上运行任何内容。除非您已经在主线程上,否则您确实需要在主线程上分派所有与UI相关的工作。

大多数与UI相关的操作都需要在主线程上执行,才能正常工作。但是仅仅使用
UI…
类本身并不能确保它在主线程上运行

这是你作为程序员的工作。如果您在后台执行某些操作(如下载数据或执行长时间运行的任务),然后需要更新UI,则必须确保UI代码在主线程上完成

请记住,可以在后台线程上安全地创建
UIImage
实例。那很安全

tl;dr-否,不保证在主线程上运行任何内容。而且您确实需要在主线程上分派与UI相关的所有工作,除非您已经在主线程上。

您感到困惑

给定的调用链要么在主线程上运行,要么在后台线程上运行。您处理的大多数代码都是通过系统事件调用的,并保证在主线程上运行。从后台线程调用代码的情况非常有限。只有在这些情况下,您才需要将UIKit调用封装在代码中,将调用重定向到主线程

代码从后台线程运行的最常见原因是您以这种方式调用了它—通常使用Grand Central Dispatch

您可以调用如下代码:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
UIImage *overlayImage = [self faceOverlayImageFromImage:_image];
dispatch_async(dispatch_get_main_queue(), ^{
    [self fadeInNewImage:overlayImage];
});
DispatchQueue.global(qos: .userInitiated).async { [weak self] in
    //This code will be on a background thread
    //Do time-consuming work here

    //This calls back to the main thread.
    DispatchQueue.main.async { [weak self] in
        //Put your code to display your results in the UI here.
    }
}
视图控制器功能、按钮操作等始终在主线程上调用。如果系统在后台线程上调用某个方法,它将被很好地记录下来

某些接受完成处理程序的函数在后台线程上调用这些完成处理程序。例如,
NSURLSession
URLSession
)类在默认为后台线程的委托队列上调用其完成处理程序和委托方法。因此,当您将完成处理程序传递给
URLSession
的实例时,您需要确保UIKit代码包装在对
dispatch\u async()
DispatchQueue.main.async()
的调用中,或者将代码传递给主线程以执行的类似方法中。

您感到困惑

给定的调用链要么在主线程上运行,要么在后台线程上运行。您处理的大多数代码都是通过系统事件调用的,并保证在主线程上运行。从后台线程调用代码的情况非常有限。只有在这些情况下,您才需要将UIKit调用封装在代码中,将调用重定向到主线程

代码从后台线程运行的最常见原因是您以这种方式调用了它—通常使用Grand Central Dispatch

您可以调用如下代码:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
UIImage *overlayImage = [self faceOverlayImageFromImage:_image];
dispatch_async(dispatch_get_main_queue(), ^{
    [self fadeInNewImage:overlayImage];
});
DispatchQueue.global(qos: .userInitiated).async { [weak self] in
    //This code will be on a background thread
    //Do time-consuming work here

    //This calls back to the main thread.
    DispatchQueue.main.async { [weak self] in
        //Put your code to display your results in the UI here.
    }
}
视图控制器功能、按钮操作等始终在主线程上调用。如果系统在后台线程上调用某个方法,它将被很好地记录下来


某些接受完成处理程序的函数在后台线程上调用这些完成处理程序。例如,
NSURLSession
URLSession
)类在默认为后台线程的委托队列上调用其完成处理程序和委托方法。因此,当您将完成处理程序传递给
URLSession
的实例时,您需要确保您的UIKit代码包装在对
dispatch\u async()
DispatchQueue.main.async()
在Swift 3中)的调用中,或者将代码传递给主线程以执行的类似方法中。

澄清一下:通常,您需要使用dispatch的原因是您启动了一个后台线程,该线程需要进行一些UI更改。除非UI更改是通过为您处理切换到UI线程的回调完成的(例如,进度条的setProgress),否则您必须使用dispatch。要澄清的是,您需要使用dispatch的原因通常是因为您启动了后台线程,并且该线程需要进行一些UI更改。除非UI更改是通过为您处理切换到UI线程的回调完成的(例如,进度条的setProgress),否则您必须使用dispatch。