2009-06-12 5 views
8

Che cosa dice sul barattolo: mi piacerebbe utilizzare la sintassi @property/@synthesize per definire una proprietà sulla mia classe Objective-C 2.0, ma voglio inserire restrizioni sull'intervallo di valori consentito nella proprietà. Per esempio:Posso convalidare un valore @property in Objective-C usando i metodi @synthesized?

@interface MyClass : NSObject { 
    int myValue; 
} 

@property (nonatomic) int myValue; 

Implementazione:

@implementation MyClass 

@synthesize myValue(test='value >= 0'); 

Nota che la sintassi qui è solo un esempio. È questo o qualcosa di simile? In alternativa, qual è l'equivalente letterale di un setter sintetizzato, così posso garantire che io uso le stesse regole di conservazione degli oggetti nei miei setter manuali come è usato in un sintetizzatore.

+0

Probabilmente vale la pena contrassegnarlo con "cacao" e "macosx". Non ho una reputazione abbastanza alta per questo. – toholio

risposta

7

Assumendo le proprietà sono valore-chiave compatibile (come lo sarebbero se si utilizza @synthesize) si dovrebbe anche implementare chiave-valore validatori compliant. Dai un'occhiata alla documentazione Apple in merito: http://developer.apple.com/documentation/Cocoa/Conceptual/KeyValueCoding/Concepts/Validation.html

La cosa importante da notare è che la convalida non avviene automaticamente tranne quando si utilizzano determinati tipi di rilegatura. Puoi chiamare direttamente il validatore o chiamando lo validateValue:forKey:error:.

È possibile sovrascrivere il setter prodotto per chiamare il validatore prima di salvarlo, ma se si utilizzano i collegamenti, questo probabilmente non è ciò che si vuole fare poiché il validatore verrà chiamato più volte per una singola modifica.

Si noti inoltre che il validatore potrebbe modificare il valore da convalidare.

Quindi guardiamo il tuo esempio (non testato, btw.Io non sono in prossimità di un Mac):

@implementation MyClass 

@synthesize myValue; 

-(BOOL)validateMyValue:(id *)ioValue error:(NSError **)outError 
{ 
    if (*ioValue == nil) { 
    // trap this in setNilValueForKey 
    // alternative might be to create new NSNumber with value 0 here 
    return YES; 
    } 

    if ([*ioValue intValue] < 0) { 
    NSString *errorString = @"myValue must be greater than zero"; 
    NSDictionary *userInfoDict = [NSDictionary dictionaryWithObject:errorString 
                  forKey:NSLocalizedDescriptionKey]; 

    NSError *error = [[[NSError alloc] initWithDomain:@"MyValueError" 
               code:0 
              userInfo:userInfoDict] autorelease]; 

    *outError = error; 

    return NO; 
    } else { 
    return YES; 
    } 
} 

Se si volesse ignorare il setter sintetizzato e fargli fare la validazione (ancora non testata):

- (void)setMyValue:(int)value { 

    id newValue = [NSNumber numberWithInt:value]; 
    NSError *errorInfo = nil; 

    if ([self validateMyValue:&newValue error:&errorInfo]) { 
    myValue = [newValue intValue]; 
    } 
} 

Si può vedere abbiamo dovuto avvolgere il intero in un'istanza NSNumber per farlo.

+4

Secondo i documenti non si dovrebbe chiamare il metodo di convalida da un setter: http://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/KeyValueCoding/Articles/Validation.html#//apple_ref/doc/uid/20002173-166962 –

2

Quando si utilizza @synthesize vengono generati i metodi di accesso. Puoi implementare il tuo che sovrascriverà quello generato.

È possibile inserire la propria implementazione nei metodi di accesso, ad es. puoi aggiungere il controllo del valore prima dell'assegnazione e così via.

È possibile omettere l'uno o l'altro o entrambi, quelli che non si implementano verranno generati a causa di @synthesize, se si utilizza @dynamic si specifica che verranno forniti accessor in fase di compilazione o di esecuzione.

Gli utenti avranno nomi derivati ​​dal nome della proprietà myproperty e setMyproperty. Le firme dei metodi sono standard, quindi è facile da implementare. L'implementazione effettiva dipende dalla definizione della proprietà (copia, conserva, assegna) e se è di sola lettura o meno (read-only non viene impostato come accessor). Per maggiori dettagli vedi riferimento all'obiettivo-c.

Apple reference:

@synthesize Si utilizza la @synthesize parola chiave per dire al compilatore che dovrebbe sintetizzare il setter e/o metodi getter per la proprietà se non li cessione ai @blocco di implementazione.

@interface MyClass : NSObject 
{ 
    NSString *value; 
} 
@property(copy, readwrite) NSString *value; 
@end 


@implementation MyClass 
@synthesize value; 

- (NSString *)value { 
    return value; 
} 

- (void)setValue:(NSString *)newValue { 
    if (newValue != value) { 
     value = [newValue copy]; 
    } 
} 
@end 
Problemi correlati