Alterar os valores do dicionário errado ao usar o KVO com o NsoperationQueue?
-
26-09-2019 - |
Pergunta
Eu estava trabalhando com um exemplo no capítulo de simulta NSOperationQueue
trabalhando como esperado. Eu crio um NSOperationQueue
e observar seu operations
Array usando:
NSOperationQueue *newQueue = [[NSOperationQueue alloc] init];
self.queue = newQueue;
[newQueue release];
[queue addObserver:self
forKeyPath:@"operations"
options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld)
context:NULL];
Quando o primeiro NSOperation
é adicionado à fila, espero que seja adicionado ao seu subjacente operations
Array (que a documentação do iOS diz ser compatível com KVO) e, portanto, no dicionário de mudança, para encontrar um mapeamento de NSKeyValueChangeKindKey
para NSKeyValueChangeInsertion
, junto com um mapeamento de NSKeyValueChangeNewKey
para o adicionado NSOperation
. Mas eu não estava vendo nenhum tipo de valor NSKeyValueChangeInsertion
.
Eu sei que o depurador é profissional e tudo, mas, no interesse de ter algo útil para copiar aqui, iniciei meu método de observador com:
- (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);
E isso impressa:
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
é simplesmente minha subclasse de NSOperation
isso substitui main
apropriadamente, e Stalled
é simplesmente o nome do projeto.) Mas observe que o método é chamado duas vezes ao inserir uma única operação, e as duas vezes com um valor gentil de 1, que é NSKeyValueChangeSetting
, não NSKeyValueChangeInsertion
. Adicionalmente, newValue
e oldValue
parece ser a própria matriz, não o item adicionado.
Alguma ideia? Obrigado!
Solução
Os documentos dizem -operations
é compatível com o KVO, mas não especifique com quais detalhes as notificações serão. Na prática, parece que você só é informado de que ocorreu uma mudança, então teria que comparar os valores antigos e novos para descobrir o que foi inserido.
Não se esqueça que essas notificações podem ser enviadas a você em qualquer tópico!
Outras dicas
A propriedade operações do NSoperCeue não possui um tipo mutável (ele retorna NSArray*
). Portanto, ele não implementa os métodos indexados de conformidade para matrizes mutáveis, para que você nunca verá os eventos de inserção, apenas o evento de mudança para toda a matriz.
Editar
ShadowMatter levantou o fato de que o objeto realmente devolvido é um NSMutableArray
. Isso, no entanto, não muda nada. Primeiramente, Documentação da Apple é claro sobre o assunto. Se um método for anunciado para retornar um objeto imutável, você deve respeitar a API. Você não deve usar isKindOf:
Para descobrir se é realmente mutável e você definitivamente não deve alterá -lo.
A API diz que o tipo de retorno das operações é imutável e, portanto, você deve tratá -lo como tal. Mais importante para esta questão, pois não é uma propriedade de coleção mutável, não é compatível com codificação de valor -chave Para os valores de KVC de matriz mutável. Para conformidade com a coleta indexada mutável, a classe precisa
- Implementar um ou ambos os métodos
-insertObject:in<Key>AtIndex:
ou-insert<Key>:atIndexes:
.- Implementar um ou ambos os métodos
-removeObjectFrom<Key>AtIndex:
ou-remove<Key>AtIndexes:
.
(retirado diretamente do guia da Apple KVC)
O designer do NSOperationQueue
Classe projetou o operations
propriedade como imutável e, portanto, deliberadamente omitiu os métodos acima.