Como criar fila de expedição no Swift 3


403

No Swift 2, consegui criar fila com o seguinte código:

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

Mas isso não é compilado no Swift 3.

Qual é a maneira preferida de escrever isso no Swift 3?



O Swift 4 possui 3 parâmetros adicionais para criar uma fila serial. Como usá-los para criar uma fila serial? DispatchQueue.init (label:, qos:, attribute:, autoreleaseFrequency:, target
:)

@ nr5 As filas são seriais por padrão, portanto, basta usá-las DispatchQueue(label: "your-label")para uma fila serial. Todos os parâmetros extras têm valores padrão.
JBG

Respostas:


1131

Criando uma fila simultânea

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

}  

Crie uma fila serial

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

}

Obter fila principal de forma assíncrona

DispatchQueue.main.async {

}

Obter fila principal de forma síncrona

DispatchQueue.main.sync {

}

Para obter um dos threads em segundo plano

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

}

Xcode 8.2 beta 2:

Para obter um dos threads em segundo plano

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

}

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

Se você quiser aprender sobre o uso dessas filas, consulte esta resposta


3
Você pode realmente omitir attributes: .serialao criar uma fila de série: let serialQueue = DispatchQueue(label: "queuename").
kean

15
No Xcode 8 beta 4, não há opção .serial; portanto, você precisa criar uma fila serial, omitindo os atributos .current.
Oleg Sherman

Eu preciso acessar o DispatchQueue do Swift3 no objc, mas obtive o seguinte erro Não é possível inicializar uma variável do tipo '__strong dispatch_queue_t' (também conhecida como 'NSObject <OS_dispatch_queue> * __ strong') com um rvalor do tipo 'OS_dispatch_queue * _Nonnull' ao executar dispatch_queue = [Fila SwiftClass]; que é uma variável estática de DispatchQueue em rápida
ideerge

DispatchQueue.main.asynchronously (DispatchQueue.main) {self.mapView.add (self.mapPolyline)} no Swift 3.0 eu tentei com DispatchQueue.global (). Asynchronously (DispatchQueue.main) {self.mapView.add (self .mapPolyline)} mas ambos os shows o mesmo erro como "valor do tipo dispathQuoue tem nenhum membro de forma assíncrona"
Abirami Bala

11
do código do OP, por que a Apple se concentra no uso de "com.swift3.imageQueue" . Vejo que o rótulo tem 3 partes. Por que é que? o que cada parte representa? Eu não entendo a formatação
Mel

55

Compila em> = Swift 3 . Este exemplo contém a maior parte da sintaxe que precisamos.

QoS - nova sintaxe de qualidade de serviço

weak self - interromper ciclos de retenção

se o eu não estiver disponível, não faça nada

async global utility queue- para consulta de rede, não espera o resultado, é uma fila simultânea, o bloco (geralmente) não espera quando iniciado. A exceção para uma fila simultânea pode ser que, quando seu limite de tarefas foi atingido anteriormente, a fila se transforma temporariamente em uma fila serial e aguarda até que alguma tarefa anterior nessa fila seja concluída.

async main queue- para tocar na interface do usuário, o bloco não espera o resultado, mas espera pelo slot no início. A fila principal é uma fila serial.

Obviamente, você precisa adicionar alguma verificação de erro a isso ...

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

6
Quando a codificação em Swift 3, se acostumar a condensação e exclusão de 30% do seu código anterior :-)
t1ser

Obrigado pelo exemplo [do eu fraco]!
imike

11
É melhor guardque selfnão é nilno topo, de modo que nenhum do código é executado se for nil, por exemplo, guard strongSelf = self else { return }.
11786 Scott Gardner #

@ t1 Você poderia me dizer onde posso encontrar a documentação para o GCD escrita com código no Swift 3? Eu só encontrei o escrito em Objective C . Alguém aqui estava me apontando para um vídeo da WWDC, mas quero ler a documentação oficial com exemplos no Swift 3 e não há como encontrá-lo.
bibscy

11
Não use .global(qos: .background)para E / S (solicitação de rede). Use .global(qos: .default)ou em .global(qos: .utility)vez disso.
Pedro Paulo Amorim

28

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

        }
    }

}

12

Como a pergunta do OP já foi respondida acima, só quero adicionar algumas considerações de velocidade:

Faz muita diferença qual classe de prioridade você atribui à sua função assíncrona em DispatchQueue.global .

Não recomendo executar tarefas com a prioridade do encadeamento .background, especialmente no iPhone X, onde a tarefa parece estar alocada nos núcleos de baixo consumo de energia.

Aqui estão alguns dados reais de uma função computacionalmente intensiva que lê um arquivo XML (com buffer) e executa a interpolação de dados:

Nome do 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

Observe que o conjunto de dados não é o mesmo para todos os dispositivos. É o maior do iPhone X e o menor do iPhone 5s.


11
Ótima informação. Me ajudou
Morgz 24/07/1918

11
@Myk Se o usuário iniciou e / ou está aguardando os resultados, você deve usar .userInitiated ou .userInteractive para que qualquer outra operação seja retornada. Na maioria dos outros casos, o padrão seria uma boa escolha.
Cosmin

6

Fiz isso e isso é especialmente importante se você deseja atualizar sua interface do usuário para mostrar novos dados sem que o usuário perceba, como no UITableView ou no UIPickerView.

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

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 a Fila de operação se precisar preencher os objetos (rótulos, visualização de imagem, visualização de texto) no seu controlador de exibição


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

Eu refiz seu código no Xcode 8, Swift 3 e as alterações são marcadas em contraste com a sua versão do Swift 2.


Parece mais limpo do que eu escrevi. Obrigado.
gosborne3

2

Swift 3

Se você deseja encerrar o código rapidamente, deseja alterar o storyboard. Qualquer tipo de alteração pertence à visualização do aplicativo.

mas você deseja usar o método de despacho, seu aplicativo não falhará

método assíncrono

DispatchQueue.main.async 
{
 //Write code here                                   

}

método de sincronização

DispatchQueue.main.sync 
{
     //Write code here                                  

}

Eu quero usar o método assíncrono no tempo de chamada do serviço, meu código é DispatchQueue.main.async {let objstory1 = self.storyboard? .InstantiateViewController (withIdentifier: "HomeViewController") as! HomeViewController _ = self.navigationController? .PushViewController (objstory1, animado: false)}
Amul4608

11
Nunca usoDispatchQueue.main.sync
trickster77777

Sincronizar chamadas na fila principal definitivamente causará problemas.
Tofu Warrior

2
DispatchQueue.main.async(execute: {

// write code

})

Fila serial:

let serial = DispatchQueue(label: "Queuename")

serial.sync { 

 //Code Here

}

Fila simultânea:

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

concurrent.sync {

 //Code Here
}

Isso não cria uma fila de despacho, apenas coloca você na fila principal após um tique no loop de execução.
buildsucceeded


1
 let newQueue = DispatchQueue(label: "newname")
 newQueue.sync { 

 // your code

 }

1

Atualização para o swift 5

Fila serial

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

Fila simultânea

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

concurrentQueue.async {
// code to execute
}

Da documentação da Apple :

Parâmetros

rótulo

Um rótulo de cadeia para anexar à fila para identificá-lo exclusivamente em ferramentas de depuração, como Instrumentos, amostra, stackshots e relatórios de falha. Como aplicativos, bibliotecas e estruturas podem criar suas próprias filas de despacho, um estilo de nomeação de DNS reverso (com.example.myqueue) é recomendado. Este parâmetro é opcional e pode ser NULL.

qos

O nível de qualidade de serviço a ser associado à fila. Este valor determina a prioridade na qual o sistema agenda tarefas para execução. Para obter uma lista dos valores possíveis, consulte DispatchQoS.QoSClass.

atributos

Os atributos a serem associados à fila. Inclua o atributo simultâneo para criar uma fila de expedição que execute tarefas simultaneamente. Se você omitir esse atributo, a fila de expedição executará tarefas em série.

autoreleaseFrequency

A frequência com a qual liberar automaticamente objetos criados pelos blocos agendados pela fila. Para obter uma lista de valores possíveis, consulte DispatchQueue.AutoreleaseFrequency .

alvo

A fila de destino na qual executar blocos. Especifique DISPATCH_TARGET_QUEUE_DEFAULT se desejar que o sistema forneça uma fila apropriada para o objeto atual.


-3

agora é simplesmente:

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

o padrão é serial, para ser simultâneo, use o argumento de atributos opcionais .concurrent


É melhor atualizar sua resposta adicionando seiralQueue.async {}. @tylemol
DawnSong

-3
DispatchQueue.main.async(execute: {
   // code
})

Obrigado por este trecho de código, que pode fornecer ajuda imediata. Uma explicação adequada melhoraria muito seu valor educacional, mostrando por que essa é uma boa solução para o problema e a tornaria mais útil para futuros leitores com perguntas semelhantes, mas não idênticas. Por favor edite sua resposta para adicionar explicação, e dar uma indicação do que limitações e premissas se aplicam.
Toby Speight

-4

Você pode criar fila de expedição usando esse código no 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*/
}

11
Desculpe, isso não está criando uma fila de despacho, está acessando a fila principal após um tique no loop de execução.
buildsucceded
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.