有人可以通过这个例子帮助我理解原始访问器:我不明白自动设置的内容和这些方法的顺序:
1.创建一个人后,willSave
第一种方法是什么? (我想是这样,因为save:
是在我们创建一个人insertNewObjectForEntityForName
)
2.在RootViewController(第二个代码块)中,然后我们使用eyeColor
调用person.eyeColor
的getter:
a)在eyeColor
中,我们称之为:[self eyeColorData]
,
b)但 setPrimitiveEyeColorData
位于willSave
,只有primitiveEyeColor
存在才能访问,
c)但 setPrimitiveEyeColor
位于eyeColor
,仅在[self eyeColorData]
存在时才会被调用。所以,我对这段代码感到有点困惑,有人可以帮帮我吗?
这是关于eyeColor
和eyeColorData
的代码:
@dynamic eyeColorData;
@dynamic eyeColor;
@interface AWPerson (PrimitiveAccessors)
- (UIColor *)primitiveEyeColor;
- (void)setPrimitiveEyeColor:(UIColor *)value;
- (NSData *)primitiveEyeColorData;
- (void)setPrimitiveEyeColorData:(NSData *)value;
@end
+ (id)personInManagedObjectContext:(NSManagedObjectContext *)moc {
return [NSEntityDescription
insertNewObjectForEntityForName:@"Person"
inManagedObjectContext:moc];
}
+ (id)randomPersonInManagedObjectContext:(NSManagedObjectContext *)moc {
AWPerson *randomPerson = [self personInManagedObjectContext:moc];
//...
randomPerson.eyeColor = [self randomColor]; //setter eyeColor
return randomPerson;
}
+ (UIColor *)randomColor {
static NSArray *colorsArray = nil;
if( !colorsArray ) {
colorsArray = [[NSArray alloc] initWithObjects:
[UIColor lightGrayColor],
[UIColor blueColor],
[UIColor greenColor], nil];
}
int randomIndex = arc4random() % [colorsArray count];
return [colorsArray objectAtIndex:randomIndex];
}
- (void)willSave {
UIColor *color = [self primitiveEyeColor];
if( color ) {
[self setPrimitiveEyeColorData:
[NSKeyedArchiver archivedDataWithRootObject:color]];
} else {
[self setPrimitiveEyeColorData:nil];
}
[super willSave];
}
- (UIColor *)eyeColor {
[self willAccessValueForKey:@"eyeColor"];
UIColor *tmpValue = [self primitiveEyeColor];
[self didAccessValueForKey:@"eyeColor"];
if( tmpValue ) return tmpValue;
NSData *colorData = [self eyeColorData];
if( !colorData ) return nil;
tmpValue = [NSKeyedUnarchiver unarchiveObjectWithData:colorData];
[self setPrimitiveEyeColor:tmpValue];
return tmpValue;
}
RootViewController中的:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
AWPerson *person = [[self fetchedResultsController] objectAtIndexPath:indexPath];
[cell setBackgroundColor:person.eyeColor];
}
由于
答案 0 :(得分:1)
编辑 - 添加了有关willSave
的信息
要回答第一个问题,只要保存对象,就会调用willSave(使用save
方法)。所以调用的第一个方法将是类方法之一(用于创建对象)或init,然后,因为你说对象在创建之后就被保存了,所以会调用willSave。
我认为理解这一点的关键是要意识到eyeColor
,primitiveEyeColor
和它们的setter最终都与内存中的同一个变量(名为eyeColor的iVar)进行交互。不同之处在于是否调用了setter / getter中的代码(在本例中为- (UIColor *)eyeColor {
函数)。
只需几种不同的方式与之互动:
[self primitiveEyeColor];
- 直接读取iVar的值。[self setPrimitiveEyeColor:tmpValue];
- 直接设置iVar的值。[self eyeColor]
- 这会调用您班级中的- (UIColor *)eyeColor
方法(最终应该检索iVar或其表示形式)。[self setEyeColor:value]
- 这会调用您班级中的- (void)setEyeColor:(UIColor *)newColor
方法。请注意,在这种情况下,它不存在,所以它只是调用基元方法(并做KVO魔术)。在这个特定的代码中,它们使用“非标准持久属性”,因为NSManagedObject不支持UIColor。阅读它here。
编辑2
回答你的其他问题:
a)
randomPerson.eyeColor = [self randomColor]
中的颜色是 可以[self primitiveEyeColor]
访问(willSave
)吗?
是的,一旦设置了eyeColor(通过setEyeColor
方法或setPrimitiveEyeColor
方法),您可以从primitiveEyeColor
读取它并返回相同的值。
请注意,设置后,eyeColor
和primitiveEyeColor
会返回相同的值,并且可以从您班级的任何位置调用(不只是willSave
)。
b)如果
[self primitiveEyeColor] != nil
:eyeColor
,则该行: 因此,if( tmpValue ) return tmpValue;
应始终如实...... 如果eyeColorData
始终返回UIColor *tmpValue = [self primitiveEyeColor]
,我们何时可以取消归档-(UIColor *)eyeColor
?
如果eyeColorData
为零,则此方法仅查看willSave
(在上次调用eyeColor
期间存储的内容)。这是一个优化,因为我们可以跳过所有这些,并且如果我们愿意,每次都可以取消归档eyeColorData
。在这种情况下,一旦将值取消归档或设置为新值,它将始终存储该值并返回它,以便我们不必再次调用unarchive。
此外,我认为这里真的是一个错误(尽管可能是设计)。假设我们执行以下步骤:
eyeColor
设置为随机颜色(让我们说蓝色)。eyeColor
设为nil 现在,如果使用[self eyeColor]
检查颜色,它会看到primitiveEyeColor为nil
并再次取消归档eyeColorData
,因此返回先前存储的蓝色。您可能应该覆盖set函数,以便在eyeColorData
设置为nil
时将eyeColor
设置为nil
。这样,在将eyeColor
设置为nil
后检查nil
的值将按预期返回{{1}}。