我可以使用@synthesized方法验证Objective-C中的@property值吗?

时间:2009-06-12 02:17:11

标签: objective-c cocoa macos

它上面说的内容:我想使用@property / @synthesize语法在Objective-C 2.0类上定义属性,但我想对范围进行限制属性中允许的值。例如:

@interface MyClass : NSObject {
    int myValue;
}

@property (nonatomic) int myValue;

实现:

@implementation MyClass

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

请注意,此处的语法只是一个示例。是这样,还是可能的东西?或者,什么是合成setter的文字等价物,这样我就可以确保在手动setter中使用与合成setter中相同的对象保留规则。

2 个答案:

答案 0 :(得分:8)

假设您的属性符合键值(如果您使用@synthesize那样),您还应该实现符合键值的验证器。请查看Apple关于此事的文档:http://developer.apple.com/documentation/Cocoa/Conceptual/KeyValueCoding/Concepts/Validation.html

需要注意的重要一点是,除非使用某些类型的绑定,否则验证不会自动发生。您可以直接调用验证器,也可以调用validateValue:forKey:error:

您可以覆盖生成的setter以在保存之前调用验证器但是如果您正在使用绑定,这可能不是您想要执行的操作,因为对于单个修改,验证器可能会被多次调用。

另请注意,验证程序可能会更改要验证的值。

让我们看看你的例子(未经测试,顺便说一下。我不在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;
  }
}

如果你想覆盖合成的setter并让它进行验证(仍未经测试):

- (void)setMyValue:(int)value {

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

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

你可以看到我们必须在NSNumber实例中包装整数来执行此操作。

答案 1 :(得分:3)

使用@synthesize时,会生成访问器方法。您可以实现自己的覆盖生成的。

您可以将自己的实现放在访问器方法中,例如您可以在分配前添加值检查等。

您可以省略其中一个或两个,由于@synthesize将生成未实现的那些,如果您使用@dynamic,则指定您将在编译或运行时提供访问器。 / p>

访问者将使用从属性名称mypropertysetMyproperty派生的名称。方法签名是标准的,因此很容易实现自己的签名。实际的实现取决于属性定义(复制,保留,赋值)以及它是否为只读(只读不设置访问器)。有关更多详细信息,请参阅objective-c reference。

Apple reference:

  

@synthesize你使用@synthesize   关键字告诉编译器它   应该合成二传手和/或   如果您属性的getter方法   不要在里面供应它们   @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