私は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
コピーしたい各クラスに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;
}
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
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のコピーの通常のセマンティクスは、浅いコピーを返すことです。トピックの詳細については、 配列のコピーに関するこの質問 も参照してください。
プロパティの長いリストを持つカスタムクラスがあったので、それらを繰り返しました。
@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もこれを実装する必要があります。
これはいくつかの助けになるかもしれません。リンクは、NSKeyedArchiver
を使用してディープコピーを行う方法を示しています
http://iphonecodecenter.wordpress.com/2013/08/26/difference-between-shallow-copy-and-deep-copy/