7

Mi imbatto spesso in scelte progettuali come questa e faccio fatica un po '; Sto cercando altre prospettive.Migliore alternativa agli oggetti Objective-C "solo dati"?

Spesso desidero mantenere elenchi di, o passare attorno a blocchi di stato che sono fondamentalmente solo insiemi di valori. I valori tendono ad essere tipi primitivi: float, NSTimeIntervals, CGPoints, ecc.

La mia prima inclinazione è spesso quella di creare strutture C per questi insiemi di proprietà, ad es.

typedef struct _STATE { 
    float foo; 
    NSTimeInterval elapsed; 
    CGPoint point; 
} STATE; 

ecc

Ma strutture C non funzionano molto bene con le classi native di raccolta del cacao (NSArray, NSSet, NSDictionary), ed usando overmany di loro di monitorare un sacco di Stato si sente come si corre contro il resto del mio codice Cocoa-friendly - Finisco per avere e gestire direttamente array di strutture e passare i puntatori di struct nei messaggi, ecc.

D'altro canto, poiché le prestazioni non sono necessariamente critiche , Potrei codificare questi valori in un NSDictionary, avvolgendoli tutti nel NSValue o NSNumber, ma la sintassi risultante è difficilmente terso, e un po 'fragile, che richiede il tipo e il nome di correttezza in fase di esecuzione sia per l'inserimento e la ricerca:

[stateDict setObject:[NSNumber numberWithFloat:foo] forKey:@"bar"]; 
... 
float something = [[stateDict objectForKey:@"bar"] floatValue]; 

e alcuni tipi, come NSTimeInterval, sono solo in grado di essere usato con qualche (discutibile) hackery (tipizzato per raddoppiare in quel caso).

Infine, potrei creare oggetti contenitore di soli dati, con dati di membri privati ​​e solo getter/setter. (Questi sarebbero chiamati "bean" in Java.) Questi sono più difficili da accedere rispetto ai dizionari, più Cocoa che struct, ma mi sembrano eccessivi, specialmente se ho solo bisogno di loro come "classi interne" che sono usate per la gestione dello stato interno a un singolo tipo di oggetto.

Come fai, grande programmazione del cacao pubblica, fai questo?

risposta

14

A seconda della situazione, eseguo l'utilizzo di classi NSDictionary per dati arbitrari oppure creo classi contenitore (i tag proprietà/sintetizzazione @ in Objective C rendono questo molto semplice). Utilizzando objC per il file di intestazione:

@interface StateObject : NSObject { 
    NSNumber *foo; 
    NSTimeInterval *elapsed; 
    CGPoint point; 
} 

@property (retain) NSNumber *foo; 
@property (retain) NSTimeInterval *elapsed; 
@property (copy) CGPoint point; 

@end 

Si può quindi utilizzare @synthesize <variable> nel file .m per creare automaticamente i setter/getter. Poi, mentre NSNumbers anonimi sono ancora scontroso, si può fare:

myStateObject.foo = [NSNumber numberWithFloat:7.0]; 

Questo dovrebbe prendere la maggior parte del dolore di distanza, e permetterà di utilizzare le classi di raccolta del cacao ai dati casuale migliori intorno.

+4

+1.La creazione di classi di modelli è quasi sempre la strada da percorrere, a meno che non si disponga di un codice critico per le prestazioni in cui il sovraccarico dell'utilizzo di oggetti può causare problemi. –

+3

Grazie per questo Matt. In questo scenario, non è nemmeno necessario avvolgere float con NSNumber: si può usare la sintassi @property per accedere ai tipi primitivi. (Lo stesso vale ovviamente per NSTimeInterval, che sembra essere un float primitivo typedef.) –

2

Non necessariamente convalidare questo approccio come "migliore", ma c'è una via di mezzo tra le tue proposte: creare strutture C per contenere le informazioni e quindi avvolgere le strutture negli oggetti NSValue quando è necessario inserirle nelle strutture dati di Cocoa . Puoi vedere UIKit farlo in alcuni casi con le strutture come CGPoint nelle notifiche (e sono sicuro che anche AppKit lo fa).

Vedere "Utilizzo dei valori" in Number and Value Programming Topics for Cocoa per ulteriori informazioni.