0

有人可以通过这个示例帮助我理解原始访问器:我不明白自动设置的内容以及这些方法的顺序:

1.人被创建后,willSave第一个方法被调用了吗?(我猜save:是这样,因为在我们创建一个人之后调用insertNewObjectForEntityForName

2.在 RootViewController (第二段代码)中,我们调用eyeColorwith : person.eyeColor:
a) in的 getter eyeColor,我们调用 : [self eyeColorData],
b) but setPrimitiveEyeColorData is in willSave,只有primitiveEyeColor存在时才可以访问,
c) but setPrimitiveEyeColor is ineyeColor并且只调用如果[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];
}

谢谢

4

1 回答 1

1

编辑 - 添加了关于willSave回答您的第一个问题的信息,只要保存对象(使用该方法)
就会调用 willSave 。save因此,调用的第一个方法将是类方法之一(用于创建对象)或 init,然后,由于您说对象在创建后立即保存,因此将调用 willSave。

我认为理解这一点的关键是要认识到eyeColor,primitiveEyeColor和它们的设置器最终都与内存中的同一个变量(名为 eyeColor 的 iVar)进行交互。区别在于是否调用了 setter/getter(在本例中为- (UIColor *)eyeColor {函数)中的代码。

只有几种不同的方式可以与之交互:

  1. [self primitiveEyeColor]; - 这直接读取 iVar 的值。
  2. [self setPrimitiveEyeColor:tmpValue]; - 这直接设置 iVar 的值。
  3. [self eyeColor] - 这将调用- (UIColor *)eyeColor您的类中的方法(最终应该检索 iVar 或其表示形式)。
  4. [self setEyeColor:value] - 这会调用- (void)setEyeColor:(UIColor *)newColor你类中的方法。请注意,在这种情况下它不存在,因此它只是调用原始方法(并执行 KVO 魔术)。

在此特定代码中,他们使用“非标准持久属性”,因为 NSManagedObject 不支持 UIColor。在这里阅读。

编辑 2
回答您的其他问题:

randomPerson.eyeColor = [self randomColor]a)可以使用[self primitiveEyeColor](in ) 访问颜色willSave

是的,一旦设置了 eyeColor(通过setEyeColor方法或setPrimitiveEyeColor方法),您可以从中读取它primitiveEyeColor,它将返回相同的值。请注意,一旦它被设置,eyeColorprimitiveEyeColor返回相同的值,并且可以从你的类中的任何地方调用(不仅仅是willSave)。

b) 所以 if [self primitiveEyeColor] != nil: in eyeColor,因此 : 行 if( tmpValue ) return tmpValue;应该总是为真......我们什么时候可以取消归档eyeColorDataifUIColor *tmpValue = [self primitiveEyeColor]总是返回 in -(UIColor *)eyeColor

如果为 nil ,此方法仅查看eyeColorData(在最后一次调用期间存储的)。这是一种优化,因为我们可以跳过所有这些,如果我们愿意,每次都可以取消存档。在这种情况下,一旦一个值被取消归档或设置为一个新值,它总是存储该值并返回,这样我们就不必再次调用 unarchive。 willSaveeyeColoreyeColorData

此外,我认为这里确实存在错误(尽管它可能是设计使然)。假设我们执行以下步骤:

  1. 设置eyeColor为随机颜色(比如说蓝色)。
  2. 保存对象。
  3. 设置eyeColor为零

现在,如果您使用[self eyeColor]它检查颜色,将看到primitiveEyeColor 已重新nil归档eyeColorData并再次取消归档,因此返回之前存储的蓝色。您可能应该覆盖 set 函数,以便它设置eyeColorDatanilwheneyeColor设置为nil。这样,eyeColor在将其设置为之后检查的值将按预期nil返回。nil

于 2012-04-05T22:38:48.477 回答