web-dev-qa-db-ja.com

Objective-Cでディープコピーを作成するにはどうすればよいですか?

私はiOS開発を学んでおり、Objective-Cのディープコピーと混同しています。たとえば、以下の3つのクラスがあります。 ClassAをディープコピーしたいのですが、コピー方法を完了するように教えてもらえますか?

A:

@interface ClassA : NSObject <NSCopying>

@property (nonatomic, assign) int aInt;
@property (nonatomic, retain) ClassB *bClass;

@end

B:

@interface ClassB : NSObject <NSCopying>

@property (nonatomic, assign) int bInt;
@property (nonatomic, retain) ClassC *cClass;

@end

C:

@interface ClassC : NSObject <NSCopying>

@property (nonatomic, assign) int cInt;
@property (nonatomic, copy) NSString *str;

@end
22
Fantasy

コピーしたい各クラスにcopyWithZone:メソッドを追加する必要があります。

NB:私はこれを手書きで書きましたが、タイプミスには注意してください。

-(id) copyWithZone:(NSZone *) zone
{
    ClassA *object = [super copyWithZone:zone];
    object.aInt = self.aInt;
    object.bClass = [self.bClass copyWithZone:zone];
    return object;
}

-(id) copyWithZone:(NSZone *) zone
{
    ClassB *object = [super copyWithZone:zone];
    object.bInt = self.bInt;
    object.cClass = [self.cClass copyWithZone:zone];
    return object;
}

-(id) copyWithZone:(NSZone *) zone
{
    ClassC *object = [super copyWithZone:zone];
    object.cInt = self.cInt;
    object.str = [self.str copy];
    return object;
}
13
James Webster

http://www.techotopia.com/index.php/Copying_Objects_in_Objective-C の説明に従ってください

「これは、オブジェクトとその構成要素をアーカイブに書き込んでから、新しいオブジェクトに読み戻すことで実現できます。」

@implementation ClassA

- (id)copyWithZone:(NSZone*)zone{
    NSData *buffer;
    buffer = [NSKeyedArchiver archivedDataWithRootObject:self];
    ClassA *copy = [NSKeyedUnarchiver unarchiveObjectWithData: buffer];
    return copy;
}
@end
19
cohen72

IOSのObjective-Cは、浅いコピーと深いコピーを切り替えるための直接的な言語またはライブラリの構成を提供しません。各クラスは、「そのコピーを取得する」ことの意味を定義します。

@implementation ClassA

- (id) copyWithZone: (NSZone*) zone
{
    ClassA *copy = [super copyWithZone:zone];
    [copy setBClass:bClass]; // this would be a shallow copy
    [copy setBClass:[bClass copy]]; // this would be a deep copy
    return copy;
}

@end

もちろん、ClassBとClassCで同じ決定を行う必要があります。誤解しない限り、Objective-Cのコピーの通常のセマンティクスは、浅いコピーを返すことです。トピックの詳細については、 配列のコピーに関するこの質問 も参照してください。

11
zoul

プロパティの長いリストを持つカスタムクラスがあったので、それらを繰り返しました。

@interface MyClass : NSObject <NSCopying>

#import <objc/runtime.h>

-(id) copyWithZone: (NSZone *) zone {

    MyClass *myCopy = [[MyClass alloc] init];

    //deepCopy
    unsigned int numOfProperties;
    objc_property_t *properties = class_copyPropertyList([self class], &numOfProperties);

    for (int i = 0; i < numOfProperties; i++) {

       objc_property_t property = properties[i];
       NSString *propertyName = [[NSString alloc]initWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
       [adressCopy setValue:[[self valueForKey:propertyName] copy] forKey:propertyName];
    }
    return myCopy;
}

すべてのcustomClassPropertiesもこれを実装する必要があります。

1
Yedy

これはいくつかの助けになるかもしれません。リンクは、NSKeyedArchiverを使用してディープコピーを行う方法を示しています

http://iphonecodecenter.wordpress.com/2013/08/26/difference-between-shallow-copy-and-deep-copy/

0