2008-09-24 15 views
11

Apple documentation on -setPrimitiveValue:forKey: là mơ hồ theo hai cách khi sử dụng nó để quản lý nhiều mối quan hệ.setPrimitiveValue: forKey: và nhiều mối quan hệ

Đầu tiên họ nêu:

Nếu bạn cố gắng thiết lập một mối quan hệ với nhiều người đến một đối tượng NSMutableSet mới, nó sẽ (cuối cùng) thất bại.

Cuối cùng ?! Điều đó có nghĩa là gì? Nó sẽ thất bại sau này trong -[NSManagedObjectContext save:]? Khi một đối tượng được quản lý bị biến thành lỗi và sau đó được quay trở lại? Khi nào? Tôi có thể viết một trường hợp thử nghiệm để luôn tạo lại sự thất bại theo yêu cầu không?

Thứ hai, cung cấp mẫu mã để xử lý một cách chính xác trường hợp này, họ viết:

đầu tiên được thiết lập hiện tại sử dụng primitiveValueForKey: (đảm bảo phương pháp này không trả lại nil)

Tôi nên làm gì nếu/khi phương thức thực hiện trả lại số không? assert() nó và thất bại ngay lập tức bởi vì điều đó có nghĩa là toàn bộ đồ thị đối tượng bị hỏng và tiết kiệm sẽ dẫn đến mất dữ liệu? NSAssert() trên đó như một cảnh báo cho người gọi nhưng nhấn vào (âm thầm không làm gì)?

Ngay bây giờ tôi đang đơn giản trực tiếp gán mong muốn NS[Mutable]Set trong trường hợp đó, như vậy tôi:

- (void)setChildren:(NSSet*)value_ { 
    NSMutableSet *mutableRelationshipSet = [[[self primitiveValueForKey:@"children"] mutableCopy] autorelease]; 
    if (mutableRelationshipSet) { 
     [mutableRelationshipSet setSet:value_]; 
     [self setPrimitiveValue:mutableRelationshipSet forKey:@"children"]; 
    } else { 
     [self setPrimitiveValue:value_ forKey:@"children"]; 
    } 
} 

Có phải đó là sai?

Trả lời

6

Chỉ cần thay đổi giá trị trả lại của -primitiveValueForKey: thành một nhóm có thể thay đổi, tin tưởng rằng giá trị trả về của nó sẽ làm điều đúng.

Đảm bảo sử dụng -willChangeValueForKey:withSetMutation:usingObjects:-didChangeValueForKey:withSetMutation:usingObjects: xung quanh thao tác của bạn; bạn đã không hiển thị điều này trong mã trên của mình.

- (void)setChildren:(NSSet *)value { 
    [self willChangeValueForKey:@"children" withSetMutation:NSKeyValueSetSetMutation usingObjects:value]; 

    NSMutableSet *primitiveValue = [self primitiveValueForKey:@"children"]; 

    [primitiveValue setSet:value]; 

    [self didChangeValueForKey:@"children" withSetMutation:NSKeyValueSetSetMutation usingObjects:value]; 
} 

Nếu bạn có thể nhắm mục tiêu Leopard, bạn không phải lo lắng về điều này; bạn có thể sử dụng Core Data của built-in hỗ trợ bất động sản thay vì:

#import <CoreData/CoreData.h> 

@interface Folder : NSManagedObject 
@property (readwrite, retain) NSSet *children; 
@end 

@implementation Folder 
@dynamic children; 
@end 

Core Data sẽ tạo ra không chỉ là một getter/cặp setter cho children tài sản nhưng accessors mutable-bộ là tốt, vì vậy bạn có thể sử dụng -mutableSetValueForKey: vào nó và thao tác với kết quả tối thiểu.