1. ホーム
  2. iphone

copyWithZoneを実装する際のベストプラクティス。

2023-09-23 05:34:25

質問

の実装について、頭の中のいくつかのことを整理しようとしています。 copyWithZone: を実装することについて、いくつかのことを整理しようとしています。

// 001: Crime is a subclass of NSObject.
- (id)copyWithZone:(NSZone *)zone {
    Crime *newCrime = [[[self class] allocWithZone:zone] init];
    if(newCrime) {
        [newCrime setMonth:[self month]];
        [newCrime setCategory:[self category]];
        [newCrime setCoordinate:[self coordinate]];
        [newCrime setLocationName:[self locationName]];
        [newCrime setTitle:[self title]];
        [newCrime setSubtitle:[self subtitle]];
    }
    return newCrime;
}

// 002: Crime is not a subclass of NSObject.
- (id)copyWithZone:(NSZone *)zone {
    Crime *newCrime = [super copyWithZone:zone];
    [newCrime setMonth:[self month]];
    [newCrime setCategory:[self category]];
    [newCrime setCoordinate:[self coordinate]];
    [newCrime setLocationName:[self locationName]];
    [newCrime setTitle:[self title]];
    [newCrime setSubtitle:[self subtitle]];
    return newCrime;
}

001で

  1. クラス名を直接記述するのがベストでしょうか [[Crime allocWithZone:zone] init] を使うべきでしょうか? [[[self Class] allocWithZone:zone] init] ?

  2. を使用しても良いのでしょうか? [self month] を使ってもいいのでしょうか?それともiVarsに直接アクセスしたほうがいいのでしょうか? _month ?

どのように解決するのですか?

  1. 常に [[self class] allocWithZone:zone] を使用して、適切なクラスを使用してコピーを作成していることを確認する必要があります。002 の例は、まさにその理由を示しています。サブクラスは [super copyWithZone:zone] を呼び出し、スーパークラスのインスタンスではなく、適切なクラスのインスタンスを取得することを期待します。

  2. 私は直接ivarsにアクセスするので、後でプロパティセッターに追加するかもしれないどんな副作用(例えば、通知を生成すること)についても心配する必要はありません。サブクラスは、どのメソッドも自由にオーバーライドできることに留意してください。あなたの例では、1つのivarにつき2つのメッセージを追加で送信しています。私なら次のように実装します。

コードです。

- (id)copyWithZone:(NSZone *)zone {
    Crime *newCrime = [super copyWithZone:zone];
    newCrime->_month = [_month copyWithZone:zone];
    newCrime->_category = [_category copyWithZone:zone];
    // etc...
    return newCrime;
}

もちろん、ivarをコピーするか、保持するか、あるいは単に代入するかは、セッターが行うことを反映する必要があります。