如何在swift中使用后台线程?

 奥黛丽凵赫本 发布于 2023-01-11 15:22

如何在swift中使用线程?

dispatchOnMainThread:^{

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

}];

tobiasdm.. 675

Swift 3.0+

很多已经在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到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 - 已知问题

从Swift 1.1开始,如果没有一些修改,Apple不支持上述语法.通过QOS_CLASS_BACKGROUND实际上没有工作,而是使用Int(QOS_CLASS_BACKGROUND.value).

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

10 个回答
  • 由于上面已经回答了OP问题,我只想添加一些速度考虑因素:

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

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

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

      iPhone X:18.7s/6.3s/1.8s/1.8s/1.8s

      iPhone 7:4.6s/3.1s/3.0s/2.8s/2.6s

      iPhone 5s:7.3s/6.1s/4.0s/4.0s/3.8s

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

    2023-01-11 15:24 回答
  • 来自Jameson Quave的教程

    斯威夫特2

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

    2023-01-11 15:24 回答
  • 在Swift 4.2和Xcode 10.1中

    我们有三种类型的队列:

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

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

    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
    

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

    1.同步执行

    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: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)
        }
    }
    

    2023-01-11 15:24 回答
  • 但是很好的答案,无论如何我想分享我的面向对象的解决方案更新为swift 3.

    请检查出来:AsyncTask

    从概念上受到了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
    

    它有2种通用类型:

    BGParam - 执行时发送给任务的参数类型.

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

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

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

      beforeTask:()->Void 在执行任务之前在UI线程上调用.

      backgroundTask: (param:BGParam)->BGResult 紧接着在后台线程上调用

      afterTask:(param:BGResult)->Void 在UI线程上调用后台任务的结果

    2023-01-11 15:24 回答
  • Dan Beaulieu在swift3中的回答.

    Swift 3.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()
                    })
                }
            }
        }
    
    }
    

    用法

    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
    })
    

    2023-01-11 15:24 回答
  • 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的一些深入信息.

    2023-01-11 15:24 回答
  • Swift 3.0+

    很多已经在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到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 - 已知问题

    从Swift 1.1开始,如果没有一些修改,Apple不支持上述语法.通过QOS_CLASS_BACKGROUND实际上没有工作,而是使用Int(QOS_CLASS_BACKGROUND.value).

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

    2023-01-11 15:25 回答
  • 最佳实践是定义可以多次访问的可重用函数.

    可重复使用的功能:

    例如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?()
            }
        }
    }
    

    注:雨燕2.0,更换QOS_CLASS_USER_INITIATED.value以上QOS_CLASS_USER_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
        })
    

    2023-01-11 15:25 回答
  • 您必须从要在UI上运行的更新中分离出要在后台运行的更改:

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
        // do your task
    
        dispatch_async(dispatch_get_main_queue()) {
            // update some UI
        }
    }
    

    2023-01-11 15:25 回答
  • Swift 4.x

    把它放在一些文件中:

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

    然后在需要的地方拨打电话:

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

    2023-01-11 15:25 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有