2016-04-03 2 views
2

プロパティが「読み取り専用」として定義され、さまざまなコンポーネント間で共有される多くの「モデル」オブジェクトがあります。私は(ローカル変更可能な状態のためにそれらを使用して)、オブジェクトのローカル変更可能なコピーを作成する必要がありますいくつかのケースでは変更可能なコピーを作成するためのObjective-Cパターン

それが作成された後、オブジェクトは不変であるべきと私はむしろNSMutableCopyプロトコルを実装していません。変更されたオブジェクトは、copy + mutate操作の後に "渡される"可能性があります。

提案されたメカニズムがありますか、または「変更された」パラメータを受け取るコンストラクタを実装するだけですか?例えば

ネイティブ型にJSONを解析対象:コードで

@interface ImmutableObject : NSObject 
// various "readonly" properties 
... 
-(instancetype)initWithJSON:(NSDictionary *)jsonDictionary; 

@property (nonatomic, readonly) MyClass1 *prop1; 
@property (nonatomic, readonly) MyClass2 *prop2; 
... 
@property (nonatomic, readonly) NSArray<MyClass100 *> *prop100; 

@end 

@implementation 
-(instancetype)initWithJSON:(NSDictionary *)jsonDictionary { 
    self = [super init]; 
    [self parseDictionaryToNative:jsonDictionary]; 
    return self; 
} 
@end 

どこか:

ImmutableObject *mutated = [immutableObject mutableCopy]; // best way to accomplish this? 
// change some values... 
mutated.prop1 = ... // change the value to something new 

self.state = [mutated copy]; // save the new object 

答えて

1

@spinalwrapは正しいですが、この場合、余分なコピーを保存してから保存する必要はありません。 NSMutableArrayNSArrayのサブクラスなので、NSArrayが使用できる場所であればどこでも使用できます(これは非常に一般的です)。あなたと同じです。あなたの特定のケースでは、あなたはおそらくそれをこのようにしてください:あなたはこのコードブロックは、(あなたのためのオブジェクトの変更可能なバージョンへの参照を持っている唯一のブロックであることを知っているので

MutableObject *mutated = [immutableObject mutableCopy]; // create an instance of MutableObject 

mutated.prop1 = ... // change the value to something new 

self.state = mutated; // Since `state` is an immutable type, 
         // attempts to mutate this later will be compiler errors 

は、これは安全ですここにそれを作りました)。

は、あなたが変更可能なサブクラスを作成したら、あなたは今ちょうどNSArrayNSStringで行われているように(防御的コピーを作成するので、あなたが実際にMutableObjectかもしれない渡されるImmutableObjectいる可能性を検討し、必要がある、と述べたこと等)例:

- (void)cacheObject:(ImmutableObject *)object { 
    // Need to copy here because object might really be a MutableObject 
    [self.cache addObject:[object copy]]; 
} 

これは通常、このような、ImmutableObjectreturn selfcopyを実装し、実際のコピーとしてMutableObjectcopyを実装することによって、かなり効率的になる。

ImmutableObject。オブジェクトがすでに不変だった場合メートル

- (ImmutableObject *)copy { 
    return self; 
} 

MutableObject.m

// as in spinalwrap's example 
- (MutableObject *)mutableCopy { 
    MutableObject *instance = [MutableObject new]; 
    instance.prop1 = [self.prop1 copy]; // depends what you want here and what kind of class the properties are... do you need a deep copy? that might be a bit more work. 
    // etc... 
    return instance; 
} 

// No need to duplicate code here. Just declare it immutable; 
// no one else has a pointer to it 
- (ImmutableObject *)copy { 
    return (ImmutableObject *)[self mutableCopy]; 
} 

だからコピーはほとんど無料です。私は「かなり効率的」と言います。なぜなら、変異していない可変オブジェクトの不要なコピーがまだ残っているからです。 ObjCのこの問題に対処するために、値型のSwiftのコピーオンライトシステムが作成されました。しかし、上記はObjCの共通パターンです。

+0

クラスは非常に大きなモデルを表しているので、2つの別々のクラスを作成するのは非常に面倒でエラーが発生しやすいです。 私は、 "let"変数ではなく "var"を定義し、自動的に変更可能なバージョンを取得するような "迅速な"メカニズムが必要であると考えていました。 私は元のコピーを作成することに頼っていました(オリジナルから実際のコピーを "self"ではなく)返し、KVCを使って "readonly"プロパティを変更しました。 。 –

1

なおNSMutableArrayNSMutableData等は、それらの不変の対応は異なるクラスです。だから、この場合、ImmutableObjectクラスと同じインターフェイスで(ただしプロパティの変更が可能)MutableObjectクラスを定義し、可変オブジェクトを使用する場合はそれを使用する必要があります。

- (MutableObject *) mutableCopy 
{ 
    MutableObject *instance = [MutableObject new]; 
    instance.prop1 = [self.prop1 copy]; // depends what you want here and what kind of class the properties are... do you need a deep copy? that might be a bit more work. 
    // etc... 
    return instance; 
} 

MutableObject'scopy方法は次のようになります:

MutableObject *mutated = [immutableObject mutableCopy]; // create an instance of MutableObject 

mutated.prop1 = ... // change the value to something new 

self.state = [mutated copy]; // creates an ImmutableObject 

ImmutableObject'smutableCopyの実装のようなものである可能性があり

- (ImmutableObject *) copy 
{ 
    ImmutableObject *instance = [ImmutableObject new]; 
    instance.prop1 = [self.prop1 copy]; 
    // etc... 
    return instance; 
} 

あなたはNSMutableCopyプロトコルを使用するように強制していません正式にはできますが、可能です。

関連する問題