Eu tenho um método que aceita um bloco e um bloco de conclusão. O primeiro bloco deve ser executado em segundo plano, enquanto o bloco de conclusão deve ser executado em qualquer fila em que o método foi chamado.
Sempre usei este último dispatch_get_current_queue()
, mas parece que está obsoleto no iOS 6 ou superior. O que devo usar no lugar?
dispatch_get_current_queue()
está obsoleto no iOS 6? os documentos não dizem nada sobre issoRespostas:
O padrão de "executar em qualquer fila em que o chamador estiver" é atraente, mas, em última análise, não é uma boa ideia. Essa fila pode ser uma fila de baixa prioridade, a fila principal ou alguma outra fila com propriedades estranhas.
Minha abordagem favorita para isso é dizer "o bloco de conclusão é executado em uma fila definida pela implementação com estas propriedades: x, y, z" e deixar o bloco ser despachado para uma fila específica se o chamador quiser mais controle do que isso. Um conjunto típico de propriedades a serem especificadas seria algo como "serial, não reentrante e assíncrono em relação a qualquer outra fila visível do aplicativo".
** EDITAR **
Catfish_Man colocou um exemplo nos comentários abaixo, estou apenas adicionando na resposta dele.
fonte
Esta é fundamentalmente a abordagem errada para a API que você está descrevendo. Se uma API aceita um bloco e um bloco de conclusão para execução, os seguintes fatos precisam ser verdadeiros:
O "bloco a ser executado" deve ser executado em uma fila interna, por exemplo, uma fila privada para a API e, portanto, totalmente sob o controle dessa API. A única exceção é se a API declara especificamente que o bloco será executado na fila principal ou em uma das filas simultâneas globais.
O bloco de conclusão deve sempre ser expresso como uma tupla (fila, bloco), a menos que as mesmas suposições do nº 1 sejam verdadeiras, por exemplo, o bloco de conclusão será executado em uma fila global conhecida. Além disso, o bloco de conclusão deve ser despachado de forma assíncrona na fila passada.
Esses não são apenas pontos estilísticos, eles são totalmente necessários se a sua API deve estar protegida de impasses ou outro comportamento de caso extremo que, de outra forma, O deixará pendurado na árvore mais próxima algum dia. :-)
fonte
As outras respostas são ótimas, mas para mim a resposta é estrutural. Eu tenho um método como este que está em um Singleton:
que tem duas dependências, que são:
e
Dessa forma, centralizo minhas chamadas para despachar no outro segmento.
fonte
Você deve ter cuidado com o uso de
dispatch_get_current_queue
em primeiro lugar. Do arquivo de cabeçalho:Você pode fazer uma das duas coisas:
Mantenha uma referência à fila que você postou originalmente (se você a criou via
dispatch_queue_create
) e use-a a partir de então.Use as filas definidas pelo sistema por meio de
dispatch_get_global_queue
e mantenha um controle de qual você está usando.Efetivamente, embora antes contasse com o sistema para manter o controle da fila em que se encontra, você terá que fazer isso sozinho.
fonte
dispatch_get_current_queue()
para descobrir que fila é essa? Às vezes, o código que precisa saber em qual fila está sendo executado não tem nenhum controle ou conhecimento sobre ele. Eu tenho muito código que pode (e deve) ser executado em uma fila de segundo plano, mas ocasionalmente precisa atualizar a gui (barra de progresso, etc) e, portanto, precisa enviar dispatch_sync () para a fila principal para essas operações. Se já estiver na fila principal, dispatch_sync () irá travar para sempre. Vou levar meses para refatorar meu código para isso.A Apple foi descontinuada
dispatch_get_current_queue()
, mas deixou uma lacuna em outro lugar, então ainda podemos obter a fila de despacho atual:Isso funciona para a fila principal, pelo menos. Observe que essa
underlyingQueue
propriedade está disponível desde iOS 8.Se precisar realizar o bloco de completamento na fila original, também pode usar
OperationQueue
diretamente, quer dizer sem GCD.fonte
Para aqueles que ainda precisam comparar filas, você pode comparar filas por seus rótulos ou especificações. Verifique https://stackoverflow.com/a/23220741/1531141
fonte
Esta é uma resposta do tipo eu também. Vou falar sobre nosso caso de uso.
Temos uma camada de serviços e a camada de IU (entre outras camadas). A camada de serviços executa tarefas em segundo plano. (Tarefas de manipulação de dados, tarefas CoreData, chamadas de rede, etc.). A camada de serviço tem algumas filas de operação para satisfazer as necessidades da camada de IU.
A camada de IU depende da camada de serviços para fazer seu trabalho e, em seguida, executar um bloco de conclusão de sucesso. Este bloco pode conter o código UIKit. Um caso de uso simples é obter todas as mensagens do servidor e recarregar a visualização da coleção.
Aqui, garantimos que os blocos que são passados para a camada de serviços são despachados na fila em que o serviço foi chamado. Como dispatch_get_current_queue é um método obsoleto, usamos o NSOperationQueue.currentQueue para obter a fila atual do chamador. Nota importante sobre esta propriedade.
Como sempre chamamos nossos serviços em uma fila conhecida (Nossas filas personalizadas e Fila principal), isso funciona bem para nós. Temos casos em que o serviçoA pode chamar o serviçoB, que pode chamar o serviçoC. Como controlamos de onde a primeira chamada de serviço está sendo feita, sabemos que o restante dos serviços seguirá as mesmas regras.
Portanto, NSOperationQueue.currentQueue sempre retornará uma de nossas Filas ou MainQueue.
fonte