本例中的原始访问器

时间:2012-04-05 22:27:20

标签: objective-c core-data primitive accessor

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

1.创建一个人后,willSave第一种方法是什么? (我想是这样,因为save:是在我们创建一个人insertNewObjectForEntityForName

之后调用的

2.在RootViewController(第二个代码块)中,然后我们使用eyeColor调用person.eyeColor的getter:
a)在eyeColor中,我们称之为:[self eyeColorData]
b) setPrimitiveEyeColorData位于willSave,只有primitiveEyeColor存在才能访问, c) setPrimitiveEyeColor位于eyeColor,仅在[self eyeColorData]存在时才会被调用。所以,我对这段代码感到有点困惑,有人可以帮帮我吗?

这是关于eyeColoreyeColorData的代码:

@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];
}

由于

1 个答案:

答案 0 :(得分:1)

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

我认为理解这一点的关键是要意识到eyeColorprimitiveEyeColor和它们的setter最终都与内存中的同一个变量(名为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魔术)。
  5. 在这个特定的代码中,它们使用“非标准持久属性”,因为NSManagedObject不支持UIColor。阅读它here

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

      

    a)randomPerson.eyeColor = [self randomColor]中的颜色是   可以[self primitiveEyeColor]访问(willSave)吗?

    是的,一旦设置了eyeColor(通过setEyeColor方法或setPrimitiveEyeColor方法),您可以从primitiveEyeColor读取它并返回相同的值。 请注意,设置后,eyeColorprimitiveEyeColor会返回相同的值,并且可以从您班级的任何位置调用(不只是willSave)。

      

    b)如果[self primitiveEyeColor] != nileyeColor,则该行:   因此,if( tmpValue ) return tmpValue;应始终如实......   如果eyeColorData始终返回UIColor *tmpValue = [self primitiveEyeColor],我们何时可以取消归档-(UIColor *)eyeColor

    如果eyeColorData为零,则此方法仅查看willSave(在上次调用eyeColor期间存储的内容)。这是一个优化,因为我们可以跳过所有这些,并且如果我们愿意,每次都可以取消归档eyeColorData。在这种情况下,一旦将值取消归档或设置为新值,它将始终存储该值并返回,以便我们不必再次调用unarchive。

    此外,我认为这里真的是一个错误(尽管可能是设计)。假设我们执行以下步骤:

    1. eyeColor设置为随机颜色(让我们说蓝色)。
    2. 保存对象。
    3. eyeColor设为nil
    4. 现在,如果使用[self eyeColor]检查颜色,它会看到primitiveEyeColor为nil并再次取消归档eyeColorData,因此返回先前存储的蓝色。您可能应该覆盖set函数,以便在eyeColorData设置为nil时将eyeColor设置为nil。这样,在将eyeColor设置为nil后检查nil的值将按预期返回{{1}}。