J'ai une application qui utilise NSOperations
pour gérer les appels de service à une API Web (les appels sont basés sur CURLOperation in Jon Wight's touchcode).Pourquoi NSOperationQueue sur iPhone OS 3.1 conserve-t-il les opérations annulées depuis longtemps?
Il existe un certain appel qui télécharge des emplacements de carte lorsque le centre d'une vue de carte change de manière significative; Puisque ceux-ci peuvent s'empiler si rapidement, si vous déplacez la carte, j'essaye d'annuler agressivement les opérations périmées. Cela fonctionne très bien sur 4.0. Cependant, sur 3.1, il semble que dans certains cas, la file d'attente d'opérations conservera les opérations annulées (et libérées), causant un plantage lorsqu'elle atteindra l'endroit où elle devrait se trouver dans la file d'attente.
Voici une illustration.
Je commence par un appel de service relativement lourd dans la file d'attente:
MyLongRunningOp 0x1
L'utilisateur accède à la carte. La file d'attente ressemble maintenant à ceci:
MyLongRunningOp 0x1
MyMapOp 0x2
Ils se déplacent la carte, ce qui annule MyMapOp 0x2 et ajoute MyMapOp 0x3:
MyLongRunningOp 0x1
MyMapOp 0x3
MyMapOp 0x2
est maintenant libéré, car il a été retiré de la file d'attente. Maintenant MyLongRunningOp 0x1
finit. Dans les rappels KVO pour la définition de la clé isFinished sur MyLongRunningOp
, je vois la file d'attente d'opération gérer la notification et essayer d'ajouter le MyMapOp 0x2
à certains . Bien entendu, avec NSZombies
activé,
[MyMapOp retain]: message sent to deallocated instance 0x2
Il semble que le NSOperationQueue
est suspendu en quelque sorte à un pointeur sur l'opération annulée/sortie et tenter de l'activer après la fin de l'opération préalable.
Je n'ai pas été capable de reproduire ce comportement sur 4.0, donc je crois que c'est un bug 3.1. J'ai beaucoup de mal à contourner ce problème. Pour autant que je sache, la seule solution consiste à ne jamais annuler mes opérations, ce qui rend l'expérience sous-optimale lorsque le réseau devient incertain.
Quelqu'un d'autre a-t-il déjà vécu cela? Des idées?
Je crois que c'est correct. Au lieu de le retirer de la file d'attente, vous devriez juste lui envoyer un message -cancel, qui ne le libère pas ou le retirer de la file d'attente - mais quand il arrivera en haut de la file, il sera ignoré et relâché. – makdad