Ios 如何在swift中使用背景线程?

Ios 如何在swift中使用背景线程?,ios,swift,multithreading,dispatch-queue,Ios,Swift,Multithreading,Dispatch Queue,如何在swift中使用线程 dispatchOnMainThread:^{ NSLog(@"Block Executed On %s", dispatch_queue_get_label(dispatch_get_current_queue())); }]; 从 Swift 2 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { //All stuff here })

如何在swift中使用线程

dispatchOnMainThread:^{

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

}];

Swift 2

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
    //All stuff here
})
Swift 3.0+ 在Swift 3.0中已经有很多内容。在后台队列上运行某些内容如下所示:

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

    DispatchQueue.main.async {
        print("This is run on the main queue, after the previous code in outer block")
    }
}
Swift 1.2至2.3 Swift前1.2–已知问题 在Swift 1.1版本中,苹果不支持上述语法,除非进行一些修改。传递
QOS\u CLASS\u USER\u INITIATED
实际上不起作用,而是使用
Int(QOS\u CLASS\u USER\u INITIATED.value)


有关更多信息,请参见

最佳做法是定义可多次访问的可重用函数

可重用功能: e、 g.像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?()
        }
    }
}
注意:在Swift 2.0中,将上面的QOS\u CLASS\u USER\u INITIATED.value替换为QOS\u CLASS\u USER\u INITIATED.rawValue

用法: A.要在后台以3秒的延迟运行进程:

    backgroundThread(3.0, background: {
            // Your background function here
    })
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.延迟3秒-注意,在没有背景参数的情况下使用完成参数:

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

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

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

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

不过答案很好,无论如何,我想分享我的面向对象解决方案最新的swift 5

请查看:

从概念上讲,受android的AsyncTask启发,我用Swift编写了自己的类

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

下面是一些用法示例

例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'
例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
它有两种通用类型:

  • BGParam
    -执行时发送到任务的参数类型

  • BGResult
    -背景计算结果的类型

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

执行异步任务时,它将经历3个步骤:

  • beforeTask:()->Void
    在执行任务之前在UI线程上调用
  • backgroundTask:(param:BGParam)->bgfresult
    之后立即在后台线程上调用
  • 后任务:(param:bgfresult)->Void
    使用后台任务的结果在UI线程上调用

  • 我真的很喜欢Dan Beaulieu的答案,但它不适用于Swift 2.2,我认为我们可以避免那些讨厌的强制打开

    func backgroundThread(delay: Double = 0.0, background: (() -> Void)? = nil, completion: (() -> Void)? = nil) {
    
        dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)) {
    
            background?()
    
            if let completion = completion{
                let popTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC)))
                dispatch_after(popTime, dispatch_get_main_queue()) {
                    completion()
                }
            }
        }
    }
    
    Swift 3版本 Swift 3利用新的
    DispatchQueue
    类来管理队列和线程。要在后台线程上运行某些内容,请使用:

    let backgroundQueue = DispatchQueue(label: "com.app.queue", qos: .background)
    backgroundQueue.async {
        print("Run on background thread")
    }
    
    或者,如果您需要两行代码:

    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."
        }
    }
    

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

    Dan Beaulieu在Swift 5中的回答(自Swift 3.0.1起也起作用)

    Swift 5.0.1 用法
    由于上面已经回答了OP问题,我只想补充一些速度方面的考虑:

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

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

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

  • iPhoneX:18.7s/6.3s/1.8s/1.8s/1.8s
  • iPhone7:4.6s/3.1s/3.0s/2.8s/2.6s
  • iphone5s:7.3s/6.1s/4.0s/4.0s/3.8s

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

    Grand Central Dispatch用于在我们的iOS应用程序中处理多任务

    您可以使用此代码

    // Using time interval
    
    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+1) {
        print("Hello World")
    }
    
    // Background thread
    queue.sync {
         for i in 0..<10 {
              print("Hello", i)
         }
    }
    
    // Main thread
    for i in 20..<30 {
         print("Hello", i)
    }
    
    //使用时间间隔
    DispatchQueue.main.asyncAfter(截止日期:DispatchTime.now()+1){
    打印(“你好世界”)
    }
    //背景线程
    queue.sync{
    
    对于Swift 4.2和Xcode 10.1中的0..中的i

    我们有三种类型的队列:

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

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

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

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

    1.同步执行

    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()
    })
    
    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()
    })
    
    来自AppCoda:

    //这将同步打印意味着,它将打印1-9和100-109
    func simpleQueues(){
    let queue=DispatchQueue(标签:“com.appcoda.myqueue”)
    queue.sync{
    
    对于0中的i..Swift 4.x

    将其放入某个文件:

    background {
         //background job
         main {
           //update UI (or what you need to do in main thread)
         }
    }
    
    然后在需要的地方调用它:

    import Foundation
    
    class myThread: Thread
    {
        override func main() {
            while(true) {
                print("Running in the Thread");
                Thread.sleep(forTimeInterval: 4);
            }
        }
    }
    
    let t = myThread();
    t.start();
    
    while(true) {
        print("Main Loop");
        sleep(5);
    }
    

    在Swift 4.2中,这起作用

    public enum QueueType {
            case Main
            case Background
            case LowPriority
            case HighPriority
    
            var queue: DispatchQueue {
                switch self {
                case .Main:
                    return DispatchQueue.main
                case .Background:
                    return DispatchQueue(label: "com.app.queue",
                                         qos: .background,
                                         target: nil)
                case .LowPriority:
                    return DispatchQueue.global(qos: .userInitiated)
                case .HighPriority:
                    return DispatchQueue.global(qos: .userInitiated)
                }
            }
        }
    
        func performOn(_ queueType: QueueType, closure: @escaping () -> Void) {
            queueType.queue.async(execute: closure)
        }
    

    线程的多用途函数

    performOn(.Background) {
        //Code
    }
    
    像这样使用它:

    import Foundation
    
    typealias Dispatch = DispatchQueue
    
    extension Dispatch {
    
        static func background(_ task: @escaping () -> ()) {
            Dispatch.global(qos: .background).async {
                task()
            }
        }
    
        static func main(_ task: @escaping () -> ()) {
            Dispatch.main.async {
                task()
            }
        }
    }
    

    Swift 5

    为方便起见,请创建一个包含以下内容的文件“DispatchQueue+Extensions.swift”:

    Dispatch.background {
        // do stuff
    
        Dispatch.main { 
            // update UI
        }
    }
    
    用法:


    转换哪个部分有困难?为什么在最后一行分号之前有
    ]
    呢?如果您能解释一下您遇到了什么问题或需要帮助,这会很有帮助。如果正确的答案确实对您有帮助,您必须接受,这也会帮助其他人找到正确的解决方案。
    DispatchQueue.global(qos:.background).async{print(“在后台线程上运行”)DispatchQueue.main.async{print(“我们完成了它”)//只有bac
    
    import Foundation
    
    class myThread: Thread
    {
        override func main() {
            while(true) {
                print("Running in the Thread");
                Thread.sleep(forTimeInterval: 4);
            }
        }
    }
    
    let t = myThread();
    t.start();
    
    while(true) {
        print("Main Loop");
        sleep(5);
    }
    
    public enum QueueType {
            case Main
            case Background
            case LowPriority
            case HighPriority
    
            var queue: DispatchQueue {
                switch self {
                case .Main:
                    return DispatchQueue.main
                case .Background:
                    return DispatchQueue(label: "com.app.queue",
                                         qos: .background,
                                         target: nil)
                case .LowPriority:
                    return DispatchQueue.global(qos: .userInitiated)
                case .HighPriority:
                    return DispatchQueue.global(qos: .userInitiated)
                }
            }
        }
    
        func performOn(_ queueType: QueueType, closure: @escaping () -> Void) {
            queueType.queue.async(execute: closure)
        }
    
    performOn(.Background) {
        //Code
    }
    
    import Foundation
    
    typealias Dispatch = DispatchQueue
    
    extension Dispatch {
    
        static func background(_ task: @escaping () -> ()) {
            Dispatch.global(qos: .background).async {
                task()
            }
        }
    
        static func main(_ task: @escaping () -> ()) {
            Dispatch.main.async {
                task()
            }
        }
    }
    
    Dispatch.background {
        // do stuff
    
        Dispatch.main { 
            // update UI
        }
    }