2009-06-12 26 views
8

Điều gì nói trên tin: Tôi muốn sử dụng cú pháp @property/@synthesize để xác định thuộc tính trên lớp Objective-C 2.0 của tôi, nhưng tôi muốn đặt giới hạn trên phạm vi giá trị được phép trong thuộc tính. Ví dụ:Tôi có thể xác nhận giá trị @property trong Objective-C bằng các phương thức @synthesized không?

@interface MyClass : NSObject { 
    int myValue; 
} 

@property (nonatomic) int myValue; 

Thực hiện:

@implementation MyClass 

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

Lưu ý rằng cú pháp ở đây chỉ là một ví dụ. Đây có phải là, hoặc một cái gì đó giống như nó có thể? Cách khác, tương đương bằng chữ của một bộ tổng hợp là gì, để tôi có thể đảm bảo rằng tôi sử dụng cùng một quy tắc lưu giữ đối tượng trong các bộ định vị thủ công như được sử dụng trong một bộ tổng hợp.

+0

Điều này có thể gắn thẻ giá trị này với 'ca cao' và 'macosx'. Tôi không có một danh tiếng đủ cao cho nó. – toholio

Trả lời

7

Giả sử tài sản của bạn là Key-Value phù hợp (như họ sẽ là nếu bạn đang sử dụng @synthesize), bạn cũng nên thực hiện Key-Value xác nhận tuân thủ. Hãy xem tài liệu của Apple về vấn đề này: http://developer.apple.com/documentation/Cocoa/Conceptual/KeyValueCoding/Concepts/Validation.html

Điều quan trọng cần lưu ý là việc xác thực không xảy ra tự động trừ khi sử dụng một số loại ràng buộc nhất định. Bạn gọi trực tiếp cho bên xác nhận hoặc bằng cách gọi số validateValue:forKey:error:.

Bạn có thể ghi đè trình setter để gọi trình xác nhận trước khi lưu nó nhưng nếu bạn đang sử dụng các ràng buộc, đây có thể không phải là những gì bạn muốn làm khi trình xác thực có thể được gọi nhiều lần.

Cũng lưu ý rằng trình xác thực có thể thay đổi giá trị đang được xác thực.

Vì vậy, hãy xem ví dụ của bạn (chưa được kiểm tra, btw.Tôi không ở gần máy 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; 
    } 
} 

Nếu bạn muốn ghi đè lên các setter tổng hợp và làm cho nó thực hiện xác nhận (vẫn chưa được kiểm tra):

- (void)setMyValue:(int)value { 

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

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

Bạn có thể thấy chúng tôi phải quấn số nguyên trong một trường hợp NSNumber để làm điều này.

+4

Theo tài liệu, bạn không nên gọi phương thức xác thực từ bên trong trình thiết lập: http://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/KeyValueCoding/Articles/Validation.html#//apple_ref/doc/uid/20002173-166962 –

2

Khi bạn sử dụng @synthesize, các phương thức truy cập được tạo. Bạn có thể thực hiện của riêng bạn mà sẽ ghi đè lên một tạo ra.

Bạn có thể đặt triển khai của riêng mình bên trong phương thức truy cập, ví dụ: bạn có thể thêm giá trị kiểm tra trước khi chuyển nhượng và như vậy.

Bạn có thể dùng một hoặc cái khác hoặc cả hai mà bạn không triển khai sẽ được tạo vì @synthesize, nếu bạn sử dụng @dynamic, bạn chỉ định rằng bạn sẽ cung cấp cho người truy cập vào lúc biên dịch hoặc chạy.

Người truy cập sẽ có tên bắt nguồn từ tên thuộc tính mypropertysetMyproperty. Chữ ký của phương thức là tiêu chuẩn để dễ thực hiện. Việc thực hiện thực tế phụ thuộc vào định nghĩa thuộc tính (sao chép, giữ lại, gán) và nếu nó là chỉ đọc hay không (chỉ đọc không nhận được accessor đã đặt). Để biết thêm chi tiết, tham khảo mục tiêu-c.

Apple reference:

@synthesize Bạn sử dụng @synthesize từ khóa để nói với trình biên dịch rằng nó nên tổng hợp các setter và/hoặc phương pháp getter cho tài sản nếu bạn không cung cấp cho họ trong @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 
Các vấn đề liên quan