我的iPhone应用程序的核心数据属性的自定义访问器方法存在问题。我想做的不仅仅是拉出原始类型并返回它。我有一个可能的活动类型的NSSet,如果该对象没有primitiveType,那么我想查看该集合并返回与我的类上的另一个变量匹配的activityType。
以下是我提出的执行此操作的代码。代码的问题是我对[self willChangeValueForKey:@"type"]
的调用导致无限循环,程序不断吐出NSLog“设置类型为......” - 可能是因为我从访问器中调用了willChange? / p>
如果我取出[self willChangeValueForKey:@"type"]
我没有得到循环,程序运行正常,下次我尝试访问对象上的类型时,原始类型被正确调用。但是,当我告诉我的ManagedObjectContext是时候保存时,它告诉我没有对任何对象进行任何更改 - 因为我没有调用willChangeValueForKey - 对于对象永远不会保留对primitiveType的更改。
- (ActivityType *)type {
[self willAccessValueForKey:@"type"];
ActivityType *myType = [self primitiveType];
[self didAccessValueForKey:@"type"];
if (myType != nil) {
NSLog(@"Use primitive (%@)", [myType myDescription]);
} else {
// 1) find type
NSSet *types = self.myActivityTypes;
NSSet *foundTypes = [types objectsPassingTest:^BOOL(id obj, BOOL *stop) {
ActivityType *object = (ActivityType *) obj;
return ([object.typeName isEqualToString:self.activityTypeName]);
}];
myType = [foundTypes allObjects][0];
NSLog(@"Setting type to %@", [myType myDescription]);
// in this case we should not alert anyone since we are inside the getter?
[self willChangeValueForKey:@"type"];
[self setPrimitiveType:myType];
[self didChangeValueForKey:@"type"];
}
return myType;
}
答案 0 :(得分:1)
托管对象属性观察机制将使用访问器来检查新旧值。由于您正在更改getter中的值,因此将再次调用getter,因此您的无限循环开始。
这种延迟加载并不适用于托管对象。您可以在其他位置设置活动类型,例如awakeFromFetch或设置activityTypeName,或者如果不合适,请实现单独的访问者:
-(ActivityType*)calculatedActivityType
{
ActivityType *myType = self.activityType;
if (myType) return myType;
NSSet *types = self.myActivityTypes;
NSSet *foundTypes = [types objectsPassingTest:^BOOL(id obj, BOOL *stop) {
ActivityType *object = (ActivityType *) obj;
return ([object.typeName isEqualToString:self.activityTypeName]);
}];
myType = [foundTypes allObjects][0];
self.activityType = myType;
return myType;
}
这不会导致任何循环,因为您不在任何访问者中。
答案 1 :(得分:0)
另一种解决方案可能是访问者返回新类型而不更改基础值类型。并且......在当前队列上异步调度更改。
dispatch_async(dispatch_get_current_queue(), ^{
[self willChangeValueForKey:@"type"];
[self setPrimitiveType:myType];
[self didChangeValueForKey:@"type"];
});
这并不完美,我可以想象这可能导致您的“查找代码”被执行多次。