79

の実装について頭の中でいくつかのことを整理しようとして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. iVar のコピーに使用[self month]しても問題ありませんか、それとも iVar に直接アクセスする必要があり_monthますか?

4

4 に答える 4

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

  2. ivar に直接アクセスするので、後でプロパティ セッターに追加する可能性のある副作用 (通知の生成など) について心配する必要はありません。サブクラスは任意のメソッドを自由にオーバーライドできることに注意してください。あなたの例では、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 をコピーするか、保持するか、単に割り当てるかは、setter の動作を反映する必要があります。

于 2012-03-28T13:02:25.647 に答える
6

copyWithZone:SDK が提供するオブジェクトを使用したメソッドのデフォルトのコピー動作は「浅いコピー」です。つまり、オブジェクトを呼び出すとcopyWithZone:NSString浅いコピーは作成されますが、深いコピーは作成されません。浅いコピーと深いコピーの違いは次のとおりです。

オブジェクトの浅いコピーは、元の配列のオブジェクトへの参照のみをコピーし、それらを新しい配列に配置します。

ディープ コピーは、オブジェクトに含まれる個々のオブジェクトを実際にコピーします。copyWithZone:これは、カスタム クラス メソッドで個々のオブジェクトにメッセージを送信することによって行われます。

INSHORT : 浅いコピーを取得するにはretain、またはstrongすべてのインスタンス変数に対して呼び出します。ディープ コピーを取得するには、カスタム クラスの実装copyWithZone:ですべてのインスタンス変数を呼び出します。copyWithZone:今、選択するのはあなたの選択です。

于 2015-04-15T15:06:51.457 に答える
-1

これが私のモデルです。

#import <Foundation/Foundation.h>
@interface RSRFDAModel : NSObject


@property (nonatomic, assign) NSInteger objectId;

@property (nonatomic, copy) NSString *name;

@property (nonatomic, strong) NSArray<RSRFDAModel *> *beans;


@end


#import "RSRFDAModel.h"

@interface RSRFDAModel () <NSCopying>

@end

@implementation RSRFDAModel 


-(id)copyWithZone:(NSZone *)zone {
    RSRFDAModel *model = [[[self class] allocWithZone:zone] init];

    model.objectId = self.objectId;
    model.name = self.name;
    model.beans = [self.beans mutableCopy];

    return model;
}

@end
于 2016-08-12T07:29:52.120 に答える