2010-09-08 29 views
6

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:

  1. MyLongRunningOp 0x1

L'utilisateur accède à la carte. La file d'attente ressemble maintenant à ceci:

  1. MyLongRunningOp 0x1
  2. MyMapOp 0x2

Ils se déplacent la carte, ce qui annule MyMapOp 0x2 et ajoute MyMapOp 0x3:

  1. MyLongRunningOp 0x1
  2. 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?

Répondre

1

J'avais (ce que je crois être) un problème similaire en utilisant KVO sur NSOperations.

Juste en lisant votre description, mon premier instinct serait de vérifier les règles pour les files d'attente d'exploitation. Est-il possible qu'une fois que vous le remettez à la file d'attente, la file d'attente devrait assumer la propriété et par conséquent vous ne devriez pas le libérer manuellement? (Je ne sais pas si vous êtes ou non).

De mon expérience personnelle, et peut-être cela aidera ou non:

1) Lorsque vous annulez une op, retirer les observateurs KVO de lui. Je l'ai fait arriver KVO ne sont pas dissociés lorsque l'un des côtés est supprimé.

2) Sachez que les rappels KVO s'exécutent dans le même thread que NSOperation. Il est donc possible qu'un objet soit hors de portée entre le démarrage de l'opération et un rappel KVO.

Je pourrais être en mesure de vous donner plus d'aide si vous postez du code. J'espère que ce qui précède vous a été utile!

+0

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