Могу ли я проверить значение @property в Objective-C, используя методы @synthesized? - PullRequest
9 голосов
/ 12 июня 2009

Что это говорит о банке: я хотел бы использовать синтаксис @property / @synthesize для определения свойства в моем классе Objective-C 2.0, но я хочу наложить ограничения на диапазон значений, разрешенных в недвижимость. Например:

@interface MyClass : NSObject {
    int myValue;
}

@property (nonatomic) int myValue;

Реализация:

@implementation MyClass

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

Обратите внимание, что синтаксис здесь только пример. Это возможно или что-то похожее на это возможно? Альтернативно, что является буквальным эквивалентом синтезированного установщика, так что я могу гарантировать, что я использую те же правила хранения объектов в моих ручных установщиках, которые используются в синтезированном.

Ответы [ 2 ]

8 голосов
/ 12 июня 2009

Предполагая, что ваши свойства совместимы с Key-Value (как они будут, если вы используете @synthesize), вам также следует реализовать валидаторы, совместимые с Key-Value. Посмотрите на документацию Apple по этому вопросу: http://developer.apple.com/documentation/Cocoa/Conceptual/KeyValueCoding/Concepts/Validation.html

Важно отметить, что проверка не происходит автоматически, за исключением случаев использования определенных видов привязки. Вы можете позвонить в валидатор напрямую или по телефону validateValue:forKey:error:.

Вы можете переопределить созданный установщик для вызова валидатора перед его сохранением, но если вы используете привязки, это, вероятно, не то, что вы хотите сделать, так как валидатор, возможно, будет вызываться более одного раза для одной модификации.

Также обратите внимание, что валидатор может изменить проверяемое значение.

Итак, давайте посмотрим на ваш пример (не проверено, кстати. Я не рядом с 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;
  }
}

Если вы хотите переопределить синтезированный установщик и заставить его выполнить проверку (все еще не проверено):

- (void)setMyValue:(int)value {

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

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

Вы можете видеть, что мы должны были обернуть целое число в экземпляре NSNumber, чтобы сделать это.

3 голосов
/ 12 июня 2009

При использовании @synthesize генерируются методы доступа. Вы можете реализовать свой собственный, который перезапишет сгенерированный.

Вы можете поместить свою собственную реализацию в методы доступа, например, Вы можете добавить проверку значения перед присвоением и т. д.

Вы можете пропустить одно или другое или оба, те, которые вы не реализуете, будут сгенерированы из-за @synthesize. Если вы используете @dynamic, вы указываете, что будете предоставлять средства доступа либо во время компиляции, либо во время выполнения.

Средства доступа будут иметь имена, полученные из имен свойств myproperty и setMyproperty. Сигнатуры методов являются стандартными, поэтому их легко реализовать самостоятельно. Реальная реализация зависит от определения свойства (копировать, сохранить, назначить) и от того, доступно оно только для чтения или нет (только для чтения не получает установленный метод доступа). Для получения более подробной информации см. Ссылку на цель-c.

Справочник Apple:

@ synthesize Вы используете @synthesize ключевое слово, чтобы сказать компилятору, что это должен синтезировать сеттер и / или методы получения для свойства, если вы не поставляйте их в пределах @implementation block.

@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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...