Cómo crear cola de despacho en Swift 3

403

En Swift 2, pude crear una cola con el siguiente código:

let concurrentQueue = dispatch_queue_create("com.swift3.imageQueue", DISPATCH_QUEUE_CONCURRENT)

Pero esto no se compila en Swift 3.

¿Cuál es la forma preferida de escribir esto en Swift 3?

Karthik Kumar
fuente
2
Posible duplicado
rickster
Swift 4 tiene 3 parámetros adicionales para crear una cola en serie. ¿Cómo usarlos para crear una cola en serie? DispatchQueue.init (etiqueta:, qos:, atributos:, autoreleaseFrequency:, target
:)
@ nr5 Las colas son seriales de forma predeterminada, por lo que es suficiente usarlas solo DispatchQueue(label: "your-label")para una cola serial. Todos los parámetros adicionales tienen valores predeterminados.
jbg

Respuestas:

1131

Crear una cola concurrente

let concurrentQueue = DispatchQueue(label: "queuename", attributes: .concurrent)
concurrentQueue.sync {

}  

Crear una cola en serie

let serialQueue = DispatchQueue(label: "queuename")
serialQueue.sync { 

}

Obtener la cola principal de forma asincrónica

DispatchQueue.main.async {

}

Obtener la cola principal sincrónicamente

DispatchQueue.main.sync {

}

Para obtener uno de los hilos de fondo

DispatchQueue.global(qos: .background).async {

}

Xcode 8.2 beta 2:

Para obtener uno de los hilos de fondo

DispatchQueue.global(qos: .default).async {

}

DispatchQueue.global().async {
    // qos' default value is ´DispatchQoS.QoSClass.default`
}

Si desea aprender sobre el uso de estas colas. Vea esta respuesta

Ese perezoso iOS Guy 웃
fuente
3
En realidad se puede omitir attributes: .serialcuando se crea una cola de serie: let serialQueue = DispatchQueue(label: "queuename").
kean
15
En Xcode 8 beta 4 no hay una opción .serial, por lo que debe crear una cola en serie omitiendo el .concurrent en los atributos.
Oleg Sherman
Necesito acceder a DispatchQueue desde Swift3 en objc, pero recibí el siguiente error. No se puede inicializar una variable de tipo '__strong dispatch_queue_t' (también conocido como 'NSObject <OS_dispatch_queue> * __ strong') con un valor de tipo 'OS_dispatch_queue * _Nonnull' al hacer despacho background__queue = [Cola SwiftClass]; esa es una variable estática de DispatchQueue en swift
ideerge
DispatchQueue.main.asynchronously (DispatchQueue.main) {self.mapView.add (self.mapPolyline)} en Swift 3.0 probé con DispatchQueue.global (). Asincrónicamente (DispatchQueue.main) {self.mapView.add (self .mapPolyline)} pero ambos muestran el mismo error que "el valor del tipo dispathQuoue no tiene miembro de forma asincrónica"
Abirami Bala
1
del código del OP, ¿por qué Apple se enfoca en usar "com.swift3.imageQueue" ? Veo que la etiqueta tiene 3 partes. ¿Porqué es eso? ¿Qué significa cada parte? No obtengo el formato
Honey
55

Compila bajo> = Swift 3 . Este ejemplo contiene la mayor parte de la sintaxis que necesitamos.

QoS: nueva sintaxis de calidad de servicio

weak self - para interrumpir los ciclos de retención

si self no está disponible, no haga nada

async global utility queue- para consulta de red, no espera el resultado, es una cola concurrente, el bloque (generalmente) no espera cuando se inicia. La excepción para una cola concurrente podría ser, cuando su límite de tarea se ha alcanzado previamente, entonces la cola se convierte temporalmente en una cola en serie y espera hasta que se complete alguna tarea previa en esa cola.

async main queue- para tocar la interfaz de usuario, el bloque no espera el resultado, sino que espera su ranura al comienzo. La cola principal es una cola en serie.

Por supuesto, debe agregar alguna comprobación de errores a esto ...

DispatchQueue.global(qos: .utility).async { [weak self] () -> Void in

    guard let strongSelf = self else { return }

    strongSelf.flickrPhoto.loadLargeImage { loadedFlickrPhoto, error in

        if error != nil {
            print("error:\(error)")
        } else {
            DispatchQueue.main.async { () -> Void in
                activityIndicator.removeFromSuperview()
                strongSelf.imageView.image = strongSelf.flickrPhoto.largeImage
            }
        }
    }
}
t1ser
fuente
66
Al codificar en Swift 3, acostúmbrese a condensar y eliminar el 30% de su código anterior :-)
t1ser
¡Gracias por el ejemplo [yo débil]!
Imike
1
Es mejor guardque selfno es nilen la parte superior, por lo que ninguno de los código se ejecuta si se trata de nil, por ejemplo, guard strongSelf = self else { return }.
Scott Gardner
@ t1 ¿Podría decirme dónde puedo encontrar la documentación para GCD escrita con código en Swift 3? Sólo he encontrado un escrito en Objective C . Alguien aquí me estaba señalando un video de WWDC, pero quiero leer la documentación oficial con ejemplos en Swift 3 y no hay forma de encontrarlo.
bibscy
1
No utilizar .global(qos: .background)para IO (solicitud de red). Uso .global(qos: .default)o en su .global(qos: .utility)lugar.
Pedro Paulo Amorim
28

Compilado en XCode 8, Swift 3 https://github.com/rpthomas/Jedisware

 @IBAction func tap(_ sender: AnyObject) {

    let thisEmail = "emailaddress.com"
    let thisPassword = "myPassword" 

    DispatchQueue.global(qos: .background).async {

        // Validate user input

        let result = self.validate(thisEmail, password: thisPassword)

        // Go back to the main thread to update the UI
        DispatchQueue.main.async {
            if !result
            {
                self.displayFailureAlert()
            }

        }
    }

}
R Thomas
fuente
12

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

Hace mucha diferencia qué clase de prioridad asigna a su función asíncrona en DispatchQueue.global .

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 de 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.

Cosmin
fuente
1
Gran información Me ayudó
Morgz
1
@Myk Si el usuario ha iniciado y / o está esperando los resultados, debe usar .userInitiated o .userInteractive para que cualquier otra operación se regrese. En la mayoría de los otros casos, .default sería una buena opción.
Cosmin
6

Hice esto y esto es especialmente importante si desea actualizar su IU para mostrar nuevos datos sin que el usuario se dé cuenta como en UITableView o UIPickerView.

    DispatchQueue.main.async
 {
   /*Write your thread code here*/
 }
Asfand Shabbir
fuente
3
 DispatchQueue.main.async {
          self.collectionView?.reloadData() // Depends if you were populating a collection view or table view
    }


OperationQueue.main.addOperation {
    self.lblGenre.text = self.movGenre
}

// use Operation Queue si necesita llenar los objetos (etiquetas, vista de imagen, vista de texto) en su controlador de vista

Fritz Gerald Moran
fuente
2
   let concurrentQueue = dispatch_queue_create("com.swift3.imageQueue", DISPATCH_QUEUE_CONCURRENT) //Swift 2 version

   let concurrentQueue = DispatchQueue(label:"com.swift3.imageQueue", attributes: .concurrent) //Swift 3 version

Reformé su código en Xcode 8, Swift 3 y los cambios están marcados en contraste con su versión Swift 2.

gosborne3
fuente
Esto se ve más limpio que lo que escribí. Gracias.
gosborne3
2

Swift 3

desea llamar a un cierre en código rápido, luego desea cambiar en el guión gráfico y cualquier tipo de cambio pertenece para ver que su aplicación se bloqueará

pero desea utilizar el método de envío, su aplicación no se bloqueará

método asincrónico

DispatchQueue.main.async 
{
 //Write code here                                   

}

método de sincronización

DispatchQueue.main.sync 
{
     //Write code here                                  

}
Amul4608
fuente
Quiero utilizar el método asíncrono en el tiempo de llamadas al servicio. Mi código es DispatchQueue.main.async {let objstory1 = self.storyboard? .InstantiateViewController (withIdentifier: "HomeViewController") como! HomeViewController _ = self.navigationController? .PushViewController (objstory1, animado: falso)}
Amul4608
1
Nunca useDispatchQueue.main.sync
trickster77777
Sincronizar llamadas en la cola principal definitivamente causará problemas.
Tofu Warrior
2
DispatchQueue.main.async(execute: {

// write code

})

Cola en serie:

let serial = DispatchQueue(label: "Queuename")

serial.sync { 

 //Code Here

}

Cola concurrente:

 let concurrent = DispatchQueue(label: "Queuename", attributes: .concurrent)

concurrent.sync {

 //Code Here
}
Hitesh Chauhan
fuente
Esto no crea una cola de despacho, solo lo coloca en la cola principal después de un tic en el ciclo de ejecución.
buildsuccedyed
1

Para Swift 3

   DispatchQueue.main.async {
        // Write your code here
    }
Joseph Mikko Manoza
fuente
@ Moritz No podría estar más de acuerdo, desafortunadamente.
Orkhan Alikhanov
1
 let newQueue = DispatchQueue(label: "newname")
 newQueue.sync { 

 // your code

 }
Profundo
fuente
1

Actualización para swift 5

Cola de serie

let serialQueue = DispatchQueue.init(label: "serialQueue")
serialQueue.async {
    // code to execute
}

Cola concurrente

let concurrentQueue = DispatchQueue.init(label: "concurrentQueue", qos: .background, attributes: .concurrent, autoreleaseFrequency: .inherit, target: nil)

concurrentQueue.async {
// code to execute
}

De la documentación de Apple :

Parámetros

etiqueta

Una etiqueta de cadena para adjuntar a la cola para identificarla de forma exclusiva en las herramientas de depuración, como instrumentos, muestras, disparos de pila e informes de fallos. Debido a que las aplicaciones, las bibliotecas y los marcos pueden crear sus propias colas de despacho, se recomienda un estilo de nomenclatura de DNS inverso (com.example.myqueue). Este parámetro es opcional y puede ser NULL.

qos

El nivel de calidad de servicio para asociar con la cola. Este valor determina la prioridad a la que el sistema programa tareas para su ejecución. Para obtener una lista de valores posibles, vea DispatchQoS.QoSClass.

atributos

Los atributos para asociar con la cola. Incluya el atributo concurrente para crear una cola de despacho que ejecute tareas simultáneamente. Si omite ese atributo, la cola de despacho ejecuta tareas en serie.

AutoreleaseFrequency

La frecuencia con la que se liberan automáticamente los objetos creados por los bloques que la cola programa. Para obtener una lista de posibles valores, vea DispatchQueue.AutoreleaseFrequency .

objetivo

La cola de destino en la que ejecutar bloques. Especifique DISPATCH_TARGET_QUEUE_DEFAULT si desea que el sistema proporcione una cola que sea apropiada para el objeto actual.

Mithra Singam
fuente
-3

ahora es simplemente:

let serialQueue = DispatchQueue(label: "my serial queue")

el valor predeterminado es serial, para obtener concurrencia, utiliza el argumento de atributos opcionales .concurrent

tylernol
fuente
Será mejor que actualice su respuesta agregando seiralQueue.async {}. @tylemol
DawnSong
-3
DispatchQueue.main.async(execute: {
   // code
})
Hitesh Chauhan
fuente
Gracias por este fragmento de código, que puede proporcionar ayuda inmediata. Una explicación adecuada mejoraría enormemente su valor educativo al mostrar por qué esta es una buena solución al problema, y ​​la haría más útil para futuros lectores con preguntas similares, pero no idénticas. Por favor, editar su respuesta para agregar explicación y dar una indicación de lo que se aplican limitaciones y supuestos.
Toby Speight
-4

Puede crear la cola de despacho utilizando este código en swift 3.0

DispatchQueue.main.async
 {
   /*Write your code here*/
 }

   /* or */

let delayTime = DispatchTime.now() + Double(Int64(0.5 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)                   
DispatchQueue.main.asyncAfter(deadline: delayTime)
{
  /*Write your code here*/
}
Nand Parikh
fuente
1
Lo sentimos, eso no es crear una cola de despacho, es acceder a la cola principal después de un tic en el ciclo de ejecución.
buildsuccedyed