NSOperationQueue
tiene waitUntilAllOperationsAreFinished
, pero no quiero esperar sincrónicamente. Solo quiero ocultar el indicador de progreso en la interfaz de usuario cuando finaliza la cola.
¿Cuál es la mejor manera de lograrlo?
No puedo enviar notificaciones desde mi correo electrónico NSOperation
porque no sé cuál será el último y es [queue operations]
posible que aún no esté vacío (o peor aún, repoblado) cuando se reciba la notificación.
Respuestas:
Use KVO para observar la
operations
propiedad de su cola, luego puede saber si su cola se ha completado al verificar[queue.operations count] == 0
.En algún lugar del archivo en el que está haciendo el KVO, declare un contexto para KVO como este ( más información ):
Cuando configure su cola, haga esto:
Entonces haz esto en tu
observeValueForKeyPath
:(Esto es asumiendo que
NSOperationQueue
está en una propiedad nombradaqueue
)En algún momento antes de que su objeto se cancele por completo (o cuando deje de preocuparse por el estado de la cola), deberá cancelar el registro de KVO de esta manera:
Anexo: iOS 4.0 tiene una
NSOperationQueue.operationCount
propiedad que, según los documentos, cumple con KVO. Sin embargo, esta respuesta seguirá funcionando en iOS 4.0, por lo que sigue siendo útil para la compatibilidad con versiones anteriores.fuente
operationCount
en el mismoNSOperationQueue
objeto podría generar errores, en cuyo caso necesitarías usar el argumento de contexto correctamente. Es poco probable que ocurra, pero definitivamente es posible. (Deletrear el problema real es más útil que agregar snark + un enlace)Si espera (o desea) algo que coincida con este comportamiento:
Debe tener en cuenta que si se agregan varias operaciones "cortas" a una cola, es posible que vea este comportamiento en su lugar (porque las operaciones se inician como parte de su adición a la cola):
En mi proyecto, necesitaba saber cuándo se completó la última operación, después de que se hubiera agregado una gran cantidad de operaciones a una NSOperationQueue en serie (es decir, maxConcurrentOperationCount = 1) y solo cuando se habían completado todas.
Buscando en Google encontré esta declaración de un desarrollador de Apple en respuesta a la pregunta "¿es una serie FIFO NSoperationQueue?" -
En mi caso es posible saber cuándo se agregó la última operación a la cola. Entonces, después de agregar la última operación, agrego otra operación a la cola, de menor prioridad, que no hace más que enviar la notificación de que la cola se ha vaciado. Dada la declaración de Apple, esto garantiza que solo se envíe un aviso único después de que se hayan completado todas las operaciones.
Si las operaciones se están agregando de una manera que no permite detectar la última (es decir, no determinista), entonces creo que debe seguir los enfoques de KVO mencionados anteriormente, con una lógica de protección adicional agregada para tratar de detectar si más se pueden agregar operaciones.
:)
fuente
¿Qué tal si agrega una NSOperation que depende de todas las demás para que se ejecute al final?
fuente
Una alternativa es utilizar GCD. Refiérase a esto como referencia.
fuente
Así es como lo hago.
Configure la cola y regístrese para cambios en la propiedad de operaciones:
... y el observador (en este caso
self
) implementa:En este ejemplo, "ruleta" es una
UIActivityIndicatorView
muestra de que algo está sucediendo. Obviamente puedes cambiar para adaptarse ...fuente
for
bucle parece potencialmente costoso (¿y si cancela todas las operaciones a la vez? ¿No obtendría un rendimiento cuadrático cuando se limpia la cola?)Estoy usando una categoría para hacer esto.
NSOperationQueue + Completion.h
NSOperationQueue + Completion.m
Uso :
Fuente: https://gist.github.com/artemstepanenko/7620471
fuente
waitUntilFinished
debería serYES
A partir de IOS 13.0 , la operationCount y operación propiedades están en desuso. Es igual de sencillo realizar un seguimiento de la cantidad de operaciones en su cola y enviar una Notificación cuando todas se hayan completado. Este ejemplo también funciona con una subclase asincrónica de Operation .
A continuación se muestra una subclase de operación para operaciones asincrónicas sencillas
}
fuente
decrementOperationCount()
invoca el método?¿Qué pasa con el uso de KVO para observar la
operationCount
propiedad de la cola? Entonces te enterarías cuando la cola se vació y también cuando dejó de estar vacía. Tratar con el indicador de progreso puede ser tan simple como hacer algo como:fuente
NSOperationQueue
de 3.1 se queja de que no es compatible con KVO para la claveoperationCount
.operationCount
propiedad está presente.Agregue la última operación como:
Entonces:
fuente
Con ReactiveObjC encuentro que esto funciona muy bien:
fuente
Para su información, puede lograr esto con GCD dispatch_group en swift 3 . Puede recibir una notificación cuando finalicen todas las tareas.
fuente
Puede crear uno nuevo
NSThread
o ejecutar un selector en segundo plano y esperar allí. Cuando elNSOperationQueue
termine, puede enviar una notificación propia.Estoy pensando en algo como:
fuente
Si usa esta Operación como su clase base, podría pasar el
whenEmpty {}
bloque a OperationQueue :fuente
Sin KVO
fuente
Si llegaste aquí buscando una solución con combine, terminé escuchando mi propio objeto de estado.
fuente