ios 如何快速使用后台线程?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24056205/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 00:30:25  来源:igfitidea点击:

How to use background thread in swift?

iosswiftmultithreadingdispatch-queue

提问by Anshul

How to use threading in swift?

如何快速使用线程?

dispatchOnMainThread:^{

    NSLog(@"Block Executed On %s", dispatch_queue_get_label(dispatch_get_current_queue()));

}];

回答by tobiasdm

Swift 3.0+

斯威夫特 3.0+

A lot has been modernizedin Swift 3.0. Running something on the background thread looks like this:

Swift 3.0 中进行了很多现代化。在后台线程上运行一些东西看起来像这样:

DispatchQueue.global(qos: .background).async {
    print("This is run on the background queue")

    DispatchQueue.main.async {
        print("This is run on the main queue, after the previous code in outer block")
    }
}

Swift 1.2 through 2.3

Swift 1.2 到 2.3

let qualityOfServiceClass = QOS_CLASS_BACKGROUND
let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
dispatch_async(backgroundQueue, {
    print("This is run on the background queue")

    dispatch_async(dispatch_get_main_queue(), { () -> Void in
        print("This is run on the main queue, after the previous code in outer block")
    })
})

Pre Swift 1.2 –?Known issue

Pre Swift 1.2 –? 已知问题

As of Swift 1.1 Apple didn't support the above syntax without some modifications. Passing QOS_CLASS_BACKGROUNDdidn't actually work, instead use Int(QOS_CLASS_BACKGROUND.value).

从 Swift 1.1 开始,Apple 不进行一些修改就不再支持上述语法。传递QOS_CLASS_BACKGROUND实际上不起作用,而是使用Int(QOS_CLASS_BACKGROUND.value).

For more information see Apples documentation

有关更多信息,请参阅Apples 文档

回答by Dale Clifford

The best practice is to define a reusable function that can be accessed multiple times.

最佳实践是定义一个可以多次访问的可重用函数。

REUSABLE FUNCTION:

可重复使用的功能:

e.g. somewhere like AppDelegate.swift as a Global Function.

例如像 AppDelegate.swift 这样的地方作为全局函数。

func backgroundThread(_ delay: Double = 0.0, background: (() -> Void)? = nil, completion: (() -> Void)? = nil) {
    dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_USER_INITIATED.value), 0)) {
        background?()

        let popTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC)))
        dispatch_after(popTime, dispatch_get_main_queue()) {
            completion?()
        }
    }
}

Note: in Swift 2.0, replace QOS_CLASS_USER_INITIATED.valueabove with QOS_CLASS_USER_INITIATED.rawValueinstead

注:雨燕2.0,更换QOS_CLASS_USER_INITIATED.value以上QOS_CLASS_USER_INITIATED.rawValue代替

USAGE:

用法:

A. To run a process in the background with a delay of 3 seconds:

A. 要在后台运行一个延迟 3 秒的进程:

    backgroundThread(3.0, background: {
            // Your background function here
    })

B. To run a process in the background then run a completion in the foreground:

B. 要在后台运行进程,然后在前台运行完成:

    backgroundThread(background: {
            // Your function here to run in the background
    },
    completion: {
            // A function to run in the foreground when the background thread is complete
    })

C. To delay by 3 seconds - note use of completion parameter without background parameter:

C. 延迟 3 秒 - 注意使用没有背景参数的完成参数:

    backgroundThread(3.0, completion: {
            // Your delayed function here to be run in the foreground
    })

回答by frouo

Dan Beaulieu's answer in swift5 (also working since swift 3.0.1).

Dan Beaulieu 在 swift5 中的回答(从 swift 3.0.1 开始也有效)。

Swift 5.0.1

斯威夫特 5.0.1

extension DispatchQueue {

    static func background(delay: Double = 0.0, background: (()->Void)? = nil, completion: (() -> Void)? = nil) {
        DispatchQueue.global(qos: .background).async {
            background?()
            if let completion = completion {
                DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: {
                    completion()
                })
            }
        }
    }

}

Usage

用法

DispatchQueue.background(delay: 3.0, background: {
    // do something in background
}, completion: {
    // when background job finishes, wait 3 seconds and do something in main thread
})

DispatchQueue.background(background: {
    // do something in background
}, completion:{
    // when background job finished, do something in main thread
})

DispatchQueue.background(delay: 3.0, completion:{
    // do something in main thread after 3 seconds
})

回答by Said Sikira

Swift 3 version

斯威夫特 3 版本

Swift 3 utilizes new DispatchQueueclass to manage queues and threads. To run something on the background thread you would use:

Swift 3 使用新DispatchQueue类来管理队列和线程。要在后台线程上运行某些内容,您可以使用:

let backgroundQueue = DispatchQueue(label: "com.app.queue", qos: .background)
backgroundQueue.async {
    print("Run on background thread")
}

Or if you want something in two lines of code:

或者,如果您想要两行代码中的内容:

DispatchQueue.global(qos: .background).async {
    print("Run on background thread")

    DispatchQueue.main.async {
        print("We finished that.")
        // only back on the main thread, may you access UI:
        label.text = "Done."
    }
}

You can also get some in-depth info about GDC in Swift 3 in this tutorial.

您还可以在本教程中获得一些有关 Swift 3 中 GDC 的深入信息。

回答by alex

From Jameson Quave'stutorial

来自Jameson Quave 的教程

Swift 2

斯威夫特 2

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
    //All stuff here
})

回答by iOS

In Swift 4.2 and Xcode 10.1

在 Swift 4.2 和 Xcode 10.1 中

We have three types of Queues :

我们有三种类型的队列:

1. Main Queue:Main queue is a serial queue which is created by the system and associated with the application main thread.

1、主队列:主队列是由系统创建并与应用程序主线程相关联的串行队列。

2. Global Queue :Global queue is a concurrent queue which we can request with respect to the priority of the tasks.

2.全局队列:全局队列是一个并发队列,我们​​可以根据任务的优先级来请求。

3. Custom queues :can be created by the user. Custom concurrent queues always mapped into one of the global queues by specifying a Quality of Service property (QoS).

3. 自定义队列:可由用户创建。自定义并发队列始终通过指定服务质量属性 (QoS) 映射到全局队列之一。

DispatchQueue.main//Main thread
DispatchQueue.global(qos: .userInitiated)//?High Priority
DispatchQueue.global(qos: .userInteractive)//High Priority (Little Higher than userInitiated)
DispatchQueue.global(qos: .background)//Lowest Priority
DispatchQueue.global(qos: .default)//Normal Priority (after High but before Low)
DispatchQueue.global(qos: .utility)//Low Priority
DispatchQueue.global(qos: .unspecified)//Absence of Quality

These all Queues can be executed in two ways

这些所有队列都可以通过两种方式执行

1. Synchronous execution

1.同步执行

2. Asynchronous execution

2. 异步执行

DispatchQueue.global(qos: .background).async {
    // do your job here
    DispatchQueue.main.async {
        // update ui here
    }
}

//Perform some task and update UI immediately.
DispatchQueue.global(qos: .userInitiated).async {  
    // Perform task
    DispatchQueue.main.async {  
        // Update UI
        self.tableView.reloadData()  
    }
}

//To call or execute function after some time
DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
    //Here call your function
}

//If you want to do changes in UI use this
DispatchQueue.main.async(execute: {
    //Update UI
    self.tableView.reloadData()
})

From AppCoda : https://www.appcoda.com/grand-central-dispatch/

来自 AppCoda:https://www.appcoda.com/grand-central-dispatch/

//This will print synchronously means, it will print 1-9 & 100-109
func simpleQueues() {
    let queue = DispatchQueue(label: "com.appcoda.myqueue")

    queue.sync {
        for i in 0..<10 {
            print("", i)
        }
    }

    for i in 100..<110 {
        print("??", i)
    }
}

//This will print asynchronously 
func simpleQueues() {
    let queue = DispatchQueue(label: "com.appcoda.myqueue")

    queue.async {
        for i in 0..<10 {
            print("", i)
        }
    }

    for i in 100..<110 {
        print("??", i)
    }
}

回答by Had?i Lazar Pe?i?

Swift 4.x

斯威夫特 4.x

Put this in some file:

把它放在某个文件中:

func background(work: @escaping () -> ()) {
    DispatchQueue.global(qos: .userInitiated).async {
        work()
    }
}

func main(work: @escaping () -> ()) {
    DispatchQueue.main.async {
        work()
    }
}

and then call it where you need:

然后在需要的地方调用它:

background {
     //background job
     main {
       //update UI (or what you need to do in main thread)
     }
}

回答by phuongle

You have to separate out the changes that you want to run in the background from the updates you want to run on the UI:

您必须将要在后台运行的更改与要在 UI 上运行的更新分开:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
    // do your task

    dispatch_async(dispatch_get_main_queue()) {
        // update some UI
    }
}

回答by Nikita Kurtin

Good answers though, anyway I want to share my Object Oriented solution Up to date for swift 5.

好的答案,无论如何我想分享我的面向对象的解决方案Up to date for swift 5

please check it out: AsyncTask

请查看:AsyncTask

Conceptually inspired by android's AsyncTask, I've wrote my own class in Swift

受 android 的 AsyncTask 的概念启发,我在 Swift 中编写了自己的类

AsyncTaskenables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread.

AsyncTask可以正确且轻松地使用 UI 线程。此类允许在 UI 线程上执行后台操作并发布结果。

Here are few usage examples

以下是一些使用示例

Example 1 -

示例 1 -

AsyncTask(backgroundTask: {(p:String)->Void in//set BGParam to String and BGResult to Void
        print(p);//print the value in background thread
    }).execute("Hello async");//execute with value 'Hello async'

Example 2 -

示例 2 -

let task2=AsyncTask(beforeTask: {
           print("pre execution");//print 'pre execution' before backgroundTask
        },backgroundTask:{(p:Int)->String in//set BGParam to Int & BGResult to String
            if p>0{//check if execution value is bigger than zero
               return "positive"//pass String "poitive" to afterTask
            }
            return "negative";//otherwise pass String "negative"
        }, afterTask: {(p:String) in
            print(p);//print background task result
    });
    task2.execute(1);//execute with value 1

It has 2 generic types:

它有 2 种通用类型:

  • BGParam- the type of the parameter sent to the task upon execution.
  • BGResult- the type of the result of the background computation.

    When you create an AsyncTask you can those types to whatever you need to pass in and out of the background task, but if you don't need those types, you can mark it as unused with just setting it to: Voidor with shorter syntax: ()

  • BGParam- 执行时发送到任务的参数类型。
  • BGResult- 后台计算结果的类型。

    当您创建 AsyncTask 时,您可以将这些类型设置为您需要传入和传出后台任务的任何类型,但如果您不需要这些类型,则可以将其标记为未使用,只需将其设置为:Void或使用更短的语法:()

When an asynchronous task is executed, it goes through 3 steps:

当一个异步任务被执行时,它会经历 3 个步骤:

  1. beforeTask:()->Voidinvoked on the UI thread just before the task is executed.
  2. backgroundTask: (param:BGParam)->BGResultinvoked on the background thread immediately after
  3. afterTask:(param:BGResult)->Voidinvoked on the UI thread with result from the background task
  1. beforeTask:()->Void在执行任务之前在 UI 线程上调用。
  2. backgroundTask: (param:BGParam)->BGResult之后立即在后台线程上调用
  3. afterTask:(param:BGResult)->Void使用后台任务的结果在 UI 线程上调用

回答by Cosmin

Since the OP question has already been answered above I just want to add some speed considerations:

由于上面已经回答了 OP 问题,因此我只想添加一些速度方面的考虑:

I don't recommend running tasks with the .backgroundthread priority especially on the iPhone X where the task seems to be allocated on the low power cores.

我不建议使用.background线程优先级运行任务,尤其是在 iPhone X 上,任务似乎分配在低功耗内核上。

Here is some real data from a computationally intensive function that reads from an XML file (with buffering) and performs data interpolation:

下面是一些来自计算密集型函数的真实数据,该函数从 XML 文件(带缓冲)读取并执行数据插值:

Device name / .background/ .utility/ .default/ .userInitiated/ .userInteractive

设备名称 / .background/ .utility/ .default/ .userInitiated/ .userInteractive

  1. iPhone X: 18.7s / 6.3s / 1.8s / 1.8s / 1.8s
  2. iPhone 7: 4.6s / 3.1s / 3.0s / 2.8s / 2.6s
  3. iPhone 5s: 7.3s / 6.1s / 4.0s / 4.0s / 3.8s
  1. iPhone X:18.7s / 6.3s / 1.8s / 1.8s / 1.8s
  2. iPhone 7:4.6s / 3.1s / 3.0s / 2.8s / 2.6s
  3. iPhone 5s:7.3s / 6.1s / 4.0s / 4.0s / 3.8s

Note that the data set is not the same for all devices. It's the biggest on the iPhone X and the smallest on the iPhone 5s.

请注意,并非所有设备的数据集都相同。它是 iPhone X 上最大的,也是 iPhone 5s 上最小的。