Modifier les valeurs du dictionnaire mal lors de l'utilisation KVO avec NSOperationQueue?
-
26-09-2019 - |
Question
Je travaillais à travers un exemple dans le chapitre de la concurrence « Plus iPhone 3 de développement, » et ne peut pas se KVO sur un travail de NSOperationQueue
comme prévu. Je crée un NSOperationQueue
et observer son tableau de operations
en utilisant:
NSOperationQueue *newQueue = [[NSOperationQueue alloc] init];
self.queue = newQueue;
[newQueue release];
[queue addObserver:self
forKeyPath:@"operations"
options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld)
context:NULL];
Lorsque le premier NSOperation
est ajouté à la file d'attente, je pense qu'il soit ajouté à son tableau de operations
sous-jacente (qui la documentation iOS dit est KVO conforme) et, par conséquent, dans le dictionnaire de changement, de trouver une application de NSKeyValueChangeKindKey
à NSKeyValueChangeInsertion
, avec une application de NSKeyValueChangeNewKey
au NSOperation
ajouté. Mais je ne voyais pas une sorte de valeur NSKeyValueChangeInsertion
.
Je sais que le débogueur est pro et tout, mais dans l'intérêt d'avoir quelque chose d'utile pour copier ici, j'ai commencé ma méthode d'observation avec:
- (void) observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
NSNumber *kind = [change objectForKey:NSKeyValueChangeKindKey];
NSObject *newValue = [change objectForKey:NSKeyValueChangeNewKey];
NSObject *oldValue = [change objectForKey:NSKeyValueChangeOldKey];
NSIndexSet *indexes = [change objectForKey:NSKeyValueChangeIndexesKey];
NSLog(@"kind=%d, newValue=%@, oldValue=%@, indexes=%@",
[kind integerValue], newValue, oldValue, indexes);
Et qui imprime:
2010-11-18 20:01:56.249 Stalled[2692:6f07] kind=1, newValue=(
"<SquareRootOperation: 0x5f51b40>"
), oldValue=(
), indexes=(null)
2010-11-18 20:01:56.250 Stalled[2692:6f07] kind=1, newValue=(
"<SquareRootOperation: 0x5f51b40>"
), oldValue=(
"<SquareRootOperation: 0x5f51b40>"
), indexes=(null)
(SquareRootOperation
est tout simplement ma sous-classe de NSOperation
qui outrepasse main
de façon appropriée et Stalled
est tout simplement le nom du projet.) Mais notez que la méthode est appelée deux fois lors de l'insertion d'une seule opération, et les deux fois avec une valeur type de 1, est NSKeyValueChangeSetting
, pas NSKeyValueChangeInsertion
. De plus, newValue
et oldValue
semblent être le tableau lui-même, et non pas l'élément ajouté.
Toutes les idées? Merci!
La solution
Les documents disent -operations
est KVO conforme, mais ne précise pas à ce détail les notifications seront. Dans la pratique, il semble que vous êtes seulement dit qu'un changement a eu lieu, ainsi aurait de comparer les valeurs anciennes et nouvelles pour savoir ce qui a été inséré.
Ne pas oublier que ces notifications peuvent être envoyés sur un fil!
Autres conseils
La propriété des opérations de NSOperationQueue ne dispose pas d'un type mutable (il retourne NSArray*
). Il ne met pas en œuvre donc les indexés à plusieurs méthodes de conformité pour les tableaux mutables de sorte que vous ne verrez jamais les événements d'insertion, seul l'événement de changement pour tout le tableau.
Modifier
Shadowmatter a élevé le fait que l'objet effectivement retourné est un NSMutableArray
. Cela ne veut pas, cependant, rien changer. Tout d'abord, la documentation Apple est clair sur la question. Si une méthode est annoncé pour renvoyer un objet immuable, vous devez respecter l'API. Vous ne devez pas utiliser isKindOf:
pour savoir si elle est vraiment mutable et vous devez changer définitivement pas.
L'API indique que les opérations de retour type est immuable et vous devez donc le traiter comme tel. Plus important encore pour cette question, car il n'est pas une propriété de collection mutable, il est valeur de la clé de codage conforme aux valeurs du tableau KVC mutables. Pour le respect de la collection indexée mutable, la classe doit
- Mettre en oeuvre une ou les deux méthodes
-insertObject:in<Key>AtIndex:
ou-insert<Key>:atIndexes:
.- Mettre en oeuvre une ou les deux méthodes
-removeObjectFrom<Key>AtIndex:
ou-remove<Key>AtIndexes:
.
(prises directement à partir du guide d'Apple KVC)
Le concepteur de la classe NSOperationQueue
conçu la propriété operations
comme immuable et donc délibérément omises les méthodes ci-dessus.