我在我的NSManagedObject上使用了一些Transient属性来预先计算在依赖属性更新时只需要计算一次的东西,但是当我重置Transient属性上的值时,它永远不会被保存。
例如:
-(NSString*)age {
// notify core data to access value
[self willAccessValueForKey:@"age"];
// get primitive value
NSString* age = [self primitiveValueForKey:@"age"];
// is age already exist?
if ( age == nil ) {
// get age
age = [GlobalHelper convertToAgeStringWithUTCDateOfBirth:(NSString*)self.dateOfBirth];
// set primitive value
[self setPrimitiveValue:age forKey:@"age"];
}
// notify core data done access value
[self didAccessValueForKey:@"age"];
return age;
}
-(void)setDateOfBirth:(id)dateOfBirth {
// change value for key
[self willChangeValueForKey:@"dateOfBirth"];
[self willChangeValueForKey:@"age"];
// set primitive
[self setPrimitiveValue:dateOfBirth forKey:@"dateOfBirth"];
[self setPrimitiveValue:nil forKey:@"age"];
// did change value for key
[self didChangeValueForKey:@"age"];
[self didChangeValueForKey:@"dateOfBirth"];
}
从上面的代码可以看出,当我同步这个对象并且“dateOfBirth”字段被更新时,它尝试将“age”设置为“nil”并且当访问“age”字段时它是否为“nil” “然后计算年龄,再也不计算它。
然而问题是当我在“setDateOfBirth”设置中将“age”字段设置为“nil”时它从未保存过,当我再次访问age时,“age”属性仍然具有之前的值,但“dateOfBirth”已更新。
非常感谢与此主题远程相关的任何帮助,我对此有很大的麻烦......
编辑:上面提到的逻辑在同一个上下文(相同的线程上下文)中setter和getter调用的情况下都是完美的,只有当从具有私有队列的AFNetworking api的完成块调用setter并且从主线程调用getter时才会出现问题合并后。似乎当我从AFNetworking完成阻止的上下文保存时,它只保存dateOfBirth而不是它设置为nil的年龄值,因此在合并之后以及当主线程“age”的getter调用具有之前的值时所以它再也不会计算了。
答案 0 :(得分:1)
阅读年龄时,不应设定年龄。这似乎是非常奇怪的设计,也无法调用适当的键值编码通知。
而是遵循您原来的逻辑:如果出生日期发生变化,请更新年龄。您应该在setDateOfBirth
中执行此操作,并在age
的设置器中调用相应的键值编码通知。
-(void) setDateOfBirth:(id)newValue {
[self willChangeValueForKey:@"dateOfBirth"];
[self setPrimitiveValue:newValue forKey:@"dateOfBirth"];
[self didChangeValueForKey:@"dateOfBirth"];
self.age = [GlobalHelper
convertToAgeStringWithUTCDateOfBirth:(NSString*)newValue];
}
-(void)age {
[self willAccessValueForKey:@"age"];
NSString* age = [self primitiveValueForKey:@"age"];
[self didAccessValueForKey:@"age"];
if (age == nil) {
age = [GlobalHelper
convertToAgeStringWithUTCDateOfBirth:(NSString*)self.dateOfBirth];
}
self.age = age;
return age;
}
然而,尽管如此,你必须问自己convertAge
电话的确有多贵。在除了最极端的情况之外的所有情况中,实际上只需要一个进行转换的简单吸气剂。
另外,我认为您的dateOfBirth
属性应该具有标准的托管对象属性类型,而不是id
。它是一个字符串?然后你应该将它声明为NSString
,而不是使用id
和强制转换。