Cómo utilizar el hilo de fondo en swift?

¿Cómo usar el enhebrado rápido?

dispatchOnMainThread:^{ NSLog(@"Block Executed On %s", dispatch_queue_get_label(dispatch_get_current_queue())); }]; 

Swift 3.0+

Mucho se ha modernizado en Swift 3.0. La ejecución de algo en el hilo de fondo se ve así:

 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 a 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 – Problema conocido

A partir de Swift 1.1, Apple no admitía la syntax anterior sin algunas modificaciones. Al pasar QOS_CLASS_BACKGROUND realidad no funcionó, en su lugar usa Int(QOS_CLASS_BACKGROUND.value) .

Para más información, consulte la documentación de las manzanas

La mejor práctica es definir una función reutilizable a la que se pueda acceder varias veces.

FUNCIÓN REUTILIZABLE:

por ejemplo, en algún lugar como AppDelegate.swift como una función global.

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

Nota: en Swift 2.0, reemplace QOS_CLASS_USER_INITIATED.value anterior con QOS_CLASS_USER_INITIATED.rawValue en su lugar

USO:

A. Para ejecutar un proceso en segundo plano con un retraso de 3 segundos:

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

B. Para ejecutar un proceso en segundo plano, ejecute una terminación en primer plano:

  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. Para retrasar en 3 segundos: tenga en cuenta el uso del parámetro de finalización sin parámetro de fondo:

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

La respuesta de Dan Beaulieu en 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() }) } } } } 

Uso

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

Swift 3 versión

Swift 3 utiliza la nueva clase DispatchQueue para administrar colas e hilos. Para ejecutar algo en el hilo de fondo usaría:

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

O si quieres algo en dos líneas de código:

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

También puede obtener información detallada sobre GDC en Swift 3 en este tutorial .

Del tutorial de Jameson Quave

Swift 2

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

Debe separar los cambios que desea ejecutar en segundo plano de las actualizaciones que desea ejecutar en la IU:

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

Buenas respuestas, de todos modos, quiero compartir mi solución orientada a objetos actualizada para swift 3 .

por favor échale un vistazo: AsyncTask

Conceptualmente inspirado en AsyncTask de Android, escribí mi propia clase en Swift

AsyncTask permite el uso adecuado y fácil del subproceso de interfaz de usuario. Esta clase permite realizar operaciones en segundo plano y publicar resultados en el hilo de la interfaz de usuario.

Aquí hay algunos ejemplos de uso

Ejemplo 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' 

Ejemplo 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 

Tiene 2 tipos generics:

  • BGParam : el tipo de parámetro enviado a la tarea en la ejecución.
  • BGResult : el tipo del resultado del cálculo de fondo.

    Cuando crea una AsyncTask, puede utilizar esos tipos para lo que necesite para ingresar y salir de la tarea en segundo plano, pero si no necesita esos tipos, puede marcarlo como no utilizado con solo establecerlo en: Void o con una syntax más corta. : ()

Cuando se ejecuta una tarea asíncrona, pasa por 3 pasos:

  1. beforeTask:()->Void invocado en el subproceso de UI justo antes de que se ejecute la tarea.
  2. backgroundTask: (param:BGParam)->BGResult invocado en el hilo de fondo inmediatamente después
  3. afterTask:(param:BGResult)->Void invocado en el subproceso de UI con el resultado de la tarea de fondo

Dado que la pregunta de OP ya ha sido respondida anteriormente, solo quiero agregar algunas consideraciones de velocidad:

No recomiendo ejecutar tareas con la prioridad de subproceso .background, especialmente en el iPhone X, donde la tarea parece estar asignada en los núcleos de baja potencia.

Aquí hay algunos datos reales de una función computacionalmente intensiva que lee desde un archivo XML (con almacenamiento en búfer) y realiza la interpolación de datos:

Nombre del dispositivo / .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

Tenga en cuenta que el conjunto de datos no es el mismo para todos los dispositivos. Es el más grande en el iPhone X y el más pequeño en el iPhone 5s.

Realmente me gusta la respuesta de Dan Beaulieu, pero no funciona con Swift 2.2 y creo que podemos evitar esos desagradables forzados.

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

Grand Central Dispatch se usa para manejar tareas múltiples en nuestras aplicaciones de iOS.

Puedes usar este código

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

Más información use este enlace: https://www.programminghub.us/2018/07/integrate-dispatcher-in-swift.html

Swift 4.1

Pon esto en algún archivo:

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

y luego llámalo donde necesites:

 background { //background job main { //update UI (or what you need to do in main thread) } } 
 dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), { // Conversion into base64 string self.uploadImageString = uploadPhotoDataJPEG.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.EncodingEndLineWithCarriageReturn) }) 

En Swift 4.1 y Xcode 9.4.1

 //To call 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: { })