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

时间:2023-01-23 17:10:36

How to use threading in swift?

如何在swift中使用线程?

dispatchOnMainThread:^{

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

}];

9 个解决方案

#1


527  

Swift 3.0+

A lot has been modernized in 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

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

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

在Swift 1.1中,苹果不支持上述语法而不作任何修改。传递QOS_CLASS_BACKGROUND并没有实际工作,而是使用Int(QOS_CLASS_BACKGROUND.value)。

For more information see Apples documentation

有关更多信息,请参见苹果文档。

#2


107  

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)) {
        if(background != nil){ background!(); }

        let popTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC)))
        dispatch_after(popTime, dispatch_get_main_queue()) {
            if(completion != nil){ completion!(); }
        }
    }
}

Note: in Swift 2.0, replace QOS_CLASS_USER_INITIATED.value above with QOS_CLASS_USER_INITIATED.rawValue instead

注意:在Swift 2.0中,替换qos_class_user_start。价值与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:

在后台运行一个进程,然后在前台运行一个完成:

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

#3


38  

Dan Beaulieu's answer in swift3.

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

}

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

#4


33  

From Jameson Quave's tutorial

从詹姆逊Quave的教程

Swift 2

斯威夫特2

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

#5


30  

Swift 3 version

Swift 3 utilizes new DispatchQueue class 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.

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

#6


22  

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

#7


8  

Good answers though, anyway I want to share my Object Oriented solution Updated for swift 3.

好的答案,不管怎样,我想分享我的面向对象的解决方案,更新为swift 3。

please check it out: AsyncTask

请检查它:AsyncTask。

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

基于android的AsyncTask概念,我在Swift中编写了自己的类。

AsyncTask enables 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:

它有两个泛型类型:

  • BGParam - the type of the parameter sent to the task upon execution.
  • BGParam——执行时发送给任务的参数的类型。
  • BGResult - the type of the result of the background computation.

    BGResult——背景计算结果的类型。

    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: Void or with shorter syntax: ()

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

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

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

  1. beforeTask:()->Void invoked on the UI thread just before the task is executed.
  2. beask:()-在执行任务之前在UI线程上调用的>Void。
  3. backgroundTask: (param:BGParam)->BGResult invoked on the background thread immediately after
  4. backgroundTask: (param:BGParam)->BGResult在后台线程上调用。
  5. afterTask:(param:BGResult)->Void invoked on the UI thread with result from the background task
  6. afterTask:(param:BGResult)-在UI线程上调用的>Void,结果来自后台任务。

#8


1  

I really like Dan Beaulieu's answer, but it doesn't work with Swift 2.2 and I think we can avoid those nasty forced unwraps!

我真的很喜欢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()
            }
        }
    }
}

#9


0  

dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), {
    // Conversion into base64 string
    self.uploadImageString =  uploadPhotoDataJPEG.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.EncodingEndLineWithCarriageReturn)
})

#1


527  

Swift 3.0+

A lot has been modernized in 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

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

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

在Swift 1.1中,苹果不支持上述语法而不作任何修改。传递QOS_CLASS_BACKGROUND并没有实际工作,而是使用Int(QOS_CLASS_BACKGROUND.value)。

For more information see Apples documentation

有关更多信息,请参见苹果文档。

#2


107  

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)) {
        if(background != nil){ background!(); }

        let popTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC)))
        dispatch_after(popTime, dispatch_get_main_queue()) {
            if(completion != nil){ completion!(); }
        }
    }
}

Note: in Swift 2.0, replace QOS_CLASS_USER_INITIATED.value above with QOS_CLASS_USER_INITIATED.rawValue instead

注意:在Swift 2.0中,替换qos_class_user_start。价值与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:

在后台运行一个进程,然后在前台运行一个完成:

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

#3


38  

Dan Beaulieu's answer in swift3.

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

}

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

#4


33  

From Jameson Quave's tutorial

从詹姆逊Quave的教程

Swift 2

斯威夫特2

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

#5


30  

Swift 3 version

Swift 3 utilizes new DispatchQueue class 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.

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

#6


22  

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

#7


8  

Good answers though, anyway I want to share my Object Oriented solution Updated for swift 3.

好的答案,不管怎样,我想分享我的面向对象的解决方案,更新为swift 3。

please check it out: AsyncTask

请检查它:AsyncTask。

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

基于android的AsyncTask概念,我在Swift中编写了自己的类。

AsyncTask enables 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:

它有两个泛型类型:

  • BGParam - the type of the parameter sent to the task upon execution.
  • BGParam——执行时发送给任务的参数的类型。
  • BGResult - the type of the result of the background computation.

    BGResult——背景计算结果的类型。

    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: Void or with shorter syntax: ()

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

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

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

  1. beforeTask:()->Void invoked on the UI thread just before the task is executed.
  2. beask:()-在执行任务之前在UI线程上调用的>Void。
  3. backgroundTask: (param:BGParam)->BGResult invoked on the background thread immediately after
  4. backgroundTask: (param:BGParam)->BGResult在后台线程上调用。
  5. afterTask:(param:BGResult)->Void invoked on the UI thread with result from the background task
  6. afterTask:(param:BGResult)-在UI线程上调用的>Void,结果来自后台任务。

#8


1  

I really like Dan Beaulieu's answer, but it doesn't work with Swift 2.2 and I think we can avoid those nasty forced unwraps!

我真的很喜欢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()
            }
        }
    }
}

#9


0  

dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), {
    // Conversion into base64 string
    self.uploadImageString =  uploadPhotoDataJPEG.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.EncodingEndLineWithCarriageReturn)
})