Ich habe eine App, die NSOperations
verwendet, um Serviceaufrufe an eine Web-API zu verwalten (die Anrufe basieren auf CURLOperation in Jon Wight's touchcode).Warum hält NSOperationQueue auf dem iPhone OS 3.1 lange abgebrochene (und freigegebene) Operationen an?
Es gibt einen bestimmten Aufruf, der Kartenstandorte herunterlädt, wenn sich das Zentrum einer Kartenansicht signifikant ändert; Da diese sich so schnell stapeln können, versuche ich, wenn ich die Karte umherbewege, veraltete Operationen aggressiv abzubrechen. Es funktioniert gut auf 4.0.
Jedoch scheint es, dass in bestimmten Fällen die Operationswarteschlange an abgebrochenen (und freigegebenen) Operationen festhält, was zu einem Absturz führt, wenn sie den Ort erreicht, an dem sie sich in der Warteschlange befinden sollten.
Hier ist eine Illustration.
Ich beginne mit einem relativen Schwergewichts-Service-Aufruf in der Warteschlange:
MyLongRunningOp 0x1
Der Benutzer navigiert zu der Karte. Die Warteschlange sieht nun wie folgt aus:
MyLongRunningOp 0x1
MyMapOp 0x2
Sie bewegen sich die Karte, die MyMapOp 0x2 annulliert und fügt MyMapOp 0x3:
MyLongRunningOp 0x1
MyMapOp 0x3
MyMapOp 0x2
ist jetzt freigegeben, da es aus der Warteschlange entfernt wurde. Jetzt MyLongRunningOp 0x1
endet. In den KVO-Callbacks zum Festlegen des isFinished-Schlüssels unter MyLongRunningOp
sehe ich, dass die Operationswarteschlange die Benachrichtigung verarbeitet und versuche, die MyMapOp 0x2
zu einigen NSArray
hinzuzufügen. Natürlich mit NSZombies
aktiviert,
[MyMapOp retain]: message sent to deallocated instance 0x2
Es scheint, dass die NSOperationQueue
irgendwie auf hängt zu einem Zeiger auf den stornierten/freigegeben Betrieb und versuchen, sie zu aktivieren, nachdem die vorherige Operation beendet.
Ich konnte dieses Verhalten auf 4.0 nicht reproduzieren, also glaube ich, dass es ein 3.1-Fehler ist.
Ich habe viel Mühe, um es zu umgehen - soweit ich sagen kann, ist die einzige Problemumgehung, meine Operationen nie abzubrechen, was für eine suboptimale Erfahrung macht, wenn das Netzwerk fraglich wird.
Hat jemand anderes das erlebt? Irgendwelche Ideen?
Ich glaube, das ist richtig. Anstatt es aus der Warteschlange zu entfernen, senden Sie ihm einfach eine -cancel-Nachricht, die es nicht freigibt oder aus der Warteschlange entfernt. Wenn es jedoch an die Spitze der Warteschlange gelangt, wird es übersprungen und freigegeben. – makdad