NSManagedObject子类更新自定义属性 - 获取KVO错误

时间:2014-08-04 05:43:09

标签: cocoa core-data nsmanagedobject cocoa-bindings key-value-observing

编辑:发现NSNumber是一个不好的绑定类型。使用NSString代替解决了问题

我有一个ToDo实体,它与ToDoTitle实体有一对一的关系(“title”),而反向关系(“todos”)是to-many。即一个待办事项可以有一个标题,但标题可以有多个待办事项。

现在我想在我的NSManagedObject之上添加一个单独的NSNumber来计算“不完整的待办事项”,即它们有一个todo.todoStatus == FALSE。

看起来像这样:

@interface ToDoTitle : NSManagedObject

@property (nonatomic, strong) NSNumber * displayOrder;
@property (nonatomic, strong) NSString * title;
@property (nonatomic, strong) NSSet *todo; // this is saved in Core Data model
@property (nonatomic, strong) NSNumber *incompleteCount; // this isn't in the Core Data model

我可以调整incompleteCount getter来返回正确的项目数,这样可行:

- (NSNumber *) incompleteCount {
    [self willAccessValueForKey:@"incompleteCount"];

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"todoStatus == FALSE"];
    NSSet *incomplete = [[self primitiveValueForKey:@"todo"] filteredSetUsingPredicate: predicate];
    [self didAccessValueForKey:@"incompleteCount"];

    return @([incomplete count]);
}

现在我真正使用它的是Cocoa Bindings,在按钮上显示这个数字。绑定工作从NSButton到NSTableViewCell,模型键路径=“objectValue.managedObject.incompleteCount.stringValue”

这也可以正常工作,并且最初显示正确的数据。我还在TodoTitle中实现了这个功能,以跟踪'todo'集的变化:

+ (NSSet*) keyPathsForValuesAffectingIncompleteCount {
    return [[NSSet alloc] initWithObjects: @"todo", nil];
}

所以现在当我添加或删除ToDo对象时,每个标题的计数也会正确更新。

当我更新其中一个待办事项对象incompleteCount时,我无法弄清楚如何更新此todoStatus。我需要在ToDo托管对象中执行类似的操作:

- (void) setTodoStatus:(NSNumber *)todoStatus {
    [self willChangeValueForKey:@"todoStatus"];
    [self setPrimitiveValue:todoStatus forKey:@"todoStatus"];

    if (todoStatus.boolValue == YES) {
        self.todotitle.incompleteCount = @(self.todotitle.incompleteCount.integerValue - 1);
    }

    [self didChangeValueForKey:@"todoStatus"];

}

我收到此错误:

  

2014-08-03 22:27:26.632 CJ [9487:303]无法更新观察员    对于关键路径   “incompleteCount.stringValue”来自,大多数   可能是因为键“incompleteCount”的值已更改   没有发送适当的KVO通知。检查   符合KVO标准的ToDoTitle课程。

使用此堆栈跟踪:

2014-08-03 22:27:26.634 Contacts Journal[9487:303] (
        0   CoreFoundation                      0x00007fff8b5c525c __exceptionPreprocess + 172
        1   libobjc.A.dylib                     0x00007fff8f25be75 objc_exception_throw + 43
        2   CoreFoundation                      0x00007fff8b5c510c +[NSException raise:format:] + 204
        3   Foundation                          0x00007fff92c134b0 -[NSKeyValueNestedProperty object:withObservance:didChangeValueForKeyOrKeys:recurse:forwardingValues:] + 1003
        4   Foundation                          0x00007fff92ba6fd9 NSKeyValueDidChange + 166
        5   Foundation                          0x00007fff92babbe6 -[NSObject(NSKeyValueObserverNotification) didChangeValueForKey:] + 118
        6   CoreData                            0x00007fff88542b01 -[NSManagedObject didChangeValueForKey:] + 113
        7   CJ                    0x00000001000d664e -[ToDo setTodoStatus:] + 318
        8   CJ                    0x00000001000ff2a9 -[ToDo(ToDo_Category) updateStatusToComplete] + 345

我只是不确定以符合KVO的方式更新incompleteTodos对象。我尝试了各种各样的事情,比如在willChangeValueForKey:didChangeValueForKey:中包含电话,但似乎没有帮助:

- (void) setTodoStatus:(NSNumber *)todoStatus {
    [self willChangeValueForKey:@"todoStatus"];
    [self setPrimitiveValue:todoStatus forKey:@"todoStatus"];

    if (todoStatus.boolValue == YES) {
       [self.todotitle willChangeValueForKey:@"incompleteCount"];
       self.todotitle.incompleteCount = @(self.todotitle.incompleteCount.integerValue - 1);
       [self.todotitle didChangeValueForKey:@"incompleteCount"];
    }

    [self didChangeValueForKey:@"todoStatus"];

}

我不确定我在这里做错了什么。我也试过在TodoTitle中添加一个自定义setter,有或没有willChange / didChange调用:

- (void) setIncompleteCount:(NSNumber *)incompleteCount_ {
    incompleteCount = incompleteCount_;
}

但仍然遇到同样的问题。

知道这里有什么问题吗?

1 个答案:

答案 0 :(得分:0)

嗯,事实证明,如果我将incompleteCount类型更改为NSString而不是NSNumber,并将整数转换为字符串,它就可以正常工作! NSNumber的stringValue一定不能用绑定更新一些问题?我不知道。在此浪费了半天!