NSManagedObject come chiave NSDictionary?
-
19-09-2019 - |
Domanda
Nella mia app, ho un NSDictionary
cui chiavi dovrebbero essere le istanze di una sottoclasse di NSManagedObject
.
Il problema, tuttavia, è che NSManagedObject
non implementa il protocollo NSCopying
il che significa che nessun oggetto Core Data / istanze di NSManagedObject
possono essere utilizzati come chiavi del dizionario, anche se il metodo -[hash]
funziona bene per loro.
Was devo fare?
Soluzione
Ci sono quattro opzioni:
- Utilizzare un oggetto diverso, come la chiave del dizionario, invece, e di ricerca da questo.
[object objectID]
o+[NSValue valueWithNonretainedObject:]
sembrano la più ovvia - Usa
CFDictionaryCreateMutable()
per creare un dizionario con mantenuto chiavi, piuttosto che copiato, invece, e quindi chiamareCFDictionarySetValue()
per memorizzare gli oggetti - Su OS X o iOS6 +,
[NSMapTable mapTableWithStrongToStrongObjects]
ti dà una puramente Objective-C equivalente aCFMutableDictionary
- Implementare
NSCopying
per la vostra sottoclasse oggetto gestito, in modo da tornare auto (con un conteggio di riferimento urtato se non si sta usando ARC)
Note
+valueWithNonretainedObject:
è piuttosto pericoloso, dal momento che è possibile essere lasciato con un puntatore penzoloni; probabilmente meglio evitare.
Memorizzazione ID oggetto va bene, a parte il fatto che nuovo oggetti iniziano la vita con un temporaneo ID. Questo ID cambia poi a un permanente uno quando il contesto è salvato su disco (o -obtainPermanentIDsForObjects:…
si chiama). Il tuo codice di mappatura deve essere abbastanza intelligente per gestire questo a meno che non può garantire che tutti gli oggetti in arrivo già hanno un ID permanente.
L'implementazione NSCopying
come questo si sente un po 'icky, ma dovrebbe funzionare bene. Si dà il caso, questo è esattamente il NSURLSessionTask
approccio prende, presumo per dizionario cordialità.
Prima di OS X 10.8 Mountain Lion, è usato per essere possibile creare un NSMutableDictionary
regolare e quindi chiamare CFDictionarySetValue()
per esso. Questo non è più il caso, però; nuovi dizionari hanno ora callback copia corretta specificati giù al livello di CF, piuttosto che puramente essere una caratteristica di NSMutableDictionary
.
Altri suggerimenti
Potrebbe creare una classe wrapper, che contiene un riferimento all'istanza di NSManagedObject che si desidera utilizzare come chiave dizionario? Si potrebbe quindi rendere questa classe wrapper implementare NSCopying, insieme a un metodo di hash (forse solo chiamando il metodo hash del NSManagedObject), e utilizzare questo wrapper come chiave del dizionario.
Suggerisco di usare [[[myManagedObject objectID] URIRepresentation] absoluteString] come chiave.
Ho avuto un problema simile, in cui avevo bisogno di raggruppare più soggetti con dati aggiuntivi per ciascuno, e inizialmente provato:
@{entity1:data1, @entity2:data2, @entity3:data3}
questo non ha funzionato per la ragione di cui sopra (NSCopying), così ho fatto:
@[
@{@"entity":entity1, @"data":data1},
@{@"entity":entity2, @"data":data2},
@{@"entity":entity3, @"data":data3}
]
Ma questa soluzione ha senso solo se non è necessario accedere stile dizionario per queste entità o sei felice di iterare per trovare ciò che serve. Nel mio caso questo è stato un problema di imballaggio. Si noti che se si passa queste entità in tutto il NSManagedObjectContext deve essere lo stesso per usarli.