0

この例で誰かがプリミティブアクセサーを理解するのを手伝ってもらえますか:自動的に設定されるものとそれらのメソッドの順序がわかりません:

1.人が作成された後willSave、最初のメソッドは呼び出されますか?save:(私たちが人を作成した後に呼び出されるので、そうだと思いますinsertNewObjectForEntityForName

2. RootViewController(コードの2番目のチャンク)で、のゲッターをeyeColor:: a)で呼び出し、:person.eyeColor、b ) を呼び出しますあります。これは、存在する場合にのみアクセス可能です。存在する場合。だから、私はこのコードと少し混乱しています、誰かが私を助けることができますか?
eyeColor[self eyeColorData]
setPrimitiveEyeColorDatawillSaveprimitiveEyeColor
setPrimitiveEyeColoreyeColor[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という名前のiVar)と相互作用していることを理解することだと思いeyeColorますprimitiveEyeColor- (UIColor *)eyeColor {違いは、setter / getter(この場合は関数) のコードが呼び出されるかどうかです。

それと対話するためのいくつかの異なる方法があります:

  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
他の質問に答えるには:

a)の色は(in )randomPerson.eyeColor = [self randomColor]でアクセスできますか?[self primitiveEyeColor]willSave

はい、eyeColorが(setEyeColorメソッドまたはメソッドを介して)設定されると、setPrimitiveEyeColorそこから読み取ることができprimitiveEyeColor、同じ値が返されます。一度設定すると、同じ値eyeColorprimitiveEyeColor返し、クラスのどこからでも呼び出すことができることに注意してください(だけでなくwillSave)。

b)したがって、[self primitiveEyeColor] != nil:ineyeColorの場合、行: は常にtrueである必要があります...常にが返される場合、いつif( tmpValue ) return tmpValue;アーカイブを解除できますか?eyeColorDataUIColor *tmpValue = [self primitiveEyeColor]-(UIColor *)eyeColor

このメソッドは、がnilの場合にのみeyeColorData(への最後の呼び出し中に保存された)を調べます。これは最適化です。必要に応じて、これらすべてをスキップして、毎回アーカイブを解除することができるからです。この場合、値がアーカイブ解除されるか、新しい値に設定されると、常にその値が保存されて返されるため、再度unarchiveを呼び出す必要はありません。 willSaveeyeColoreyeColorData

また、ここにはエラーがあると私が信じていることが実際にあります(設計によるものかもしれませんが)。次の手順を実行するとします。

  1. eyeColorランダムな色(たとえば青)に設定します。
  2. オブジェクトを保存します。
  3. eyeColornilに設定

ここで、それを使用して色を確認する[self eyeColor]と、primitiveEyeColorがであることがわかり、再度nilアーカイブが解除eyeColorDataされるため、以前に保存された青色が返されます。おそらく、set関数をオーバーライドして、がに設定されたときにに設定eyeColorDataされるようにする必要があります。そうすれば、に設定した後にの値をチェックすると、期待どおりに戻ります。nileyeColornileyeColornilnil

于 2012-04-05T22:38:48.477 に答える