Dopo aver letto il valore-chiave Guida Coding programmazione, il valore-chiave Osservando Guida alla programmazione e la Modello Guida Object Attuazione, così come la lettura molte voci StackOverflow sul tema e la sperimentazione di diversi scenari di modellazione, ho sento di avere una buona conoscenza di come modellare i miei dati.Le relazioni "to-many" dovrebbero essere modellate come proprietà?
Finisco per utilizzare le proprietà dichiarate per tutti i miei attributi e le relazioni a uno, supportate da ivars privati. Per gli attributi di sola lettura che devono essere scrivibili privatamente, utilizzo l'attributo readonly
nella dichiarazione dell'interfaccia .h
, quindi ripeto la proprietà con l'attributo readwrite
in un'estensione di classe dichiarata nel file .m
. All'interno dei metodi di classe, utilizzo sempre gli accessor della proprietà con la sintassi del punto e non accedo mai direttamente agli ivars privati.
C'è tuttavia un aspetto che mi lascia ancora perplesso: come modellare correttamente a-molte relazioni, specialmente quando la raccolta deve essere pubblicamente immutabile, ma in privato mutabile (cioè i consumatori dell'oggetto modello non possono aggiungere o rimuovere oggetti a la raccolta, ma il contenuto della raccolta è gestito privatamente dalla classe).
Capisco come implementare i metodi di accesso KVC per le relazioni to-many (countOf<Key>
, objectsIn<Key>AtIndex
, ecc.) E questa è la strada che ho seguito fino ad ora.
Tuttavia, ho visto alcuni codice di esempio che utilizza le proprietà dichiarate per esporre le relazioni, non implementare i metodi di accesso KVC, ma sono ancora visibili valore-chiave. Ad esempio:
@interface MyModel : NSObject
{
// Note that the ivar is a mutable array,
// while the property is declared as an immutable array.
@private NSMutableArray *transactions_;
}
@property (nonatomic, retain, readonly) NSArray transactions;
@end
--------------------
@implementation MyModel
@synthesize transactions = transactions_;
- (void)privateMethodThatManagesTransactions
{
[[self mutableArrayValueForKey:@"transactions"] addObject:t];
}
@end
Se un oggetto di consumo si aggiunge come osservatore di un'istanza MyModel
per il percorso della chiave "transactions"
, esso sarà notificato quando vengono aggiunti o rimossi operazioni dalla collezione transactions
(purché le mutazioni sono fatto tramite il metodo mutableArrayValueForKey:
).
Per me, questo sembra il modo più pulito per esporre a molte relazioni in quanto non è necessario codificare manualmente gli accessori KVC della raccolta e mantiene il codice pulito.
Tuttavia, non sembra essere il modo in cui viene promosso dalla documentazione Apple e non posso fare a meno di chiedermi se il fatto che funzioni è solo un effetto collaterale inaffidabile.
Quindi prima di dedicarmi a una tecnica o l'altra nelle mie classi di modelli di vita reale per un progetto su cui sto iniziando a lavorare, mi piacerebbe avere l'opinione e il consiglio degli esperti sviluppatori di Cocoa.
Quindi la domanda è: se utilizzo le proprietà per modellare su molte relazioni, devo ancora implementare i metodi di accesso/mutatore KVC?
Aggiornamento
Anche quando dichiaro una proprietà a-molti come readonly
, come nell'esempio di cui sopra, il codice esterno può ancora chiamare mutableArrayValueForKey:@"transactions"
sul modello a oggetti e mutare la collezione. Questo sembra indicare che usare le proprietà dichiarate per molte relazioni non è la strada da percorrere, ma mi sembra ancora di non averlo capito ...
Mi sono appena reso conto che anche per le proprietà semplici che rappresentano gli attributi o le relazioni uno, dichiarare la proprietà come readonly in .H e riaffermarlo come readwrite in .M consente al codice esterno di modificare il valore della proprietà utilizzando KVC setValue: forKey: ... Quindi sembra che KVC permetta di bypassare la semantica espressa nella dichiarazione di proprietà in tutti i casi, quindi suppongo che non dovrei essere sorpreso di poter mutare una raccolta in sola lettura usando mutableArrayValueForKey: .. –