Copy、MutableCopy方法、copy关键字

Copy MutableCopy方法

1、对immutable对象进行copy操作,是浅复制,mutableCopy操作时深复制。
2、对mutable对象进行copy和mutableCopy都是深复制。
3、copy返回的都是不可变对象, mutableCopy返回的都是可变对象

NSString
NSString *originString = @"origin";
NSString *copyString = [originString copy];  //浅复制复制后的对象不可变
NSMutableString *mCopyString = [originString mutableCopy];//深复制复制后的对象可变
NSLog(@"origin      string %p  %p", originString, &originString);
NSLog(@"copy        string %p  %p", copyString, &copyString);
NSLog(@"mutableCopy string %p  %p", mCopyString, &mCopyString);

// 输出 origin      string 0x100d34e08  0x16f0d7e48
// 输出 copy        string 0x100d34e08  0x16f0d7e40
// 输出 mutableCopy string 0x1c4446b40  0x16f0d7e38
NSString
NSMutableString *originString2 = [NSMutableString stringWithString:@"origin"];
NSString *copyString2 = [originString2 copy];  //深复制复制后的对象不可变
NSMutableString *mCopyString2 = [originString2 mutableCopy];//深复制复制后的对象可变
NSLog(@"origin      string2 %p  %p", originString2, &originString2);
NSLog(@"copy        string2 %p  %p", copyString2, &copyString2);
NSLog(@"mutableCopy string2 %p  %p", mCopyString2, &mCopyString2);

// 输出 origin      string 0x1c805fc80  0x16f357e30
// 输出 copy        string 0xa006e696769726f6  0x16f357e28
// 输出 mutableCopy string 0x1c805e9f0  0x16f357e20
NSArray
NSArray *originArray = @[@"a", @"b", @"c"];
NSArray *copyArray = [originArray copy];//浅复制复制后的对象不可变 此时等价于copyArray = originArray
NSMutableArray *mCopyArray = [originArray mutableCopy];//深复制复制后的对象可变
NSLog(@"origin      Array %p  %p", originArray, &originArray);
NSLog(@"copy        Array %p  %p", copyArray, &copyArray);
NSLog(@"mutableCopy Array %p  %p", mCopyArray, &mCopyArray);

// 输出 origin      Array 0x1c405afa0  0x16f017df8
// 输出 copy        Array 0x1c405afa0  0x16f017df0
// 输出 mutableCopy Array 0x1c405dac0  0x16f017de8
NSMutableArray
NSMutableArray *originArray2 = [NSMutableArray arrayWithObjects: @"a", @"b", @"c", nil];
NSArray *copyArray2 = [originArray2 copy];//深复制复制后的对象不可变
NSMutableArray *mCopyArray2 = [originArray2 mutableCopy];//深复制复制后的对象可变
NSLog(@"origin      Array %p  %p", originArray2, &originArray2);
NSLog(@"copy        Array %p  %p", copyArray2, &copyArray2);
NSLog(@"mutableCopy Array %p  %p", mCopyArray2, &mCopyArray2);

// 输出 origin      Array 0x1c4055ba0  0x16f293e18
// 输出 copy        Array 0x1c4055c00  0x16f293e10
// 输出 mutableCopy Array 0x1c4055d80  0x16f293e08

Copy关键字

1、属性里的copy和strong NSString *str 声明一般用copy,如果一个NSMutableString的 *sourceStr 赋值给NSString,copy会进行深复制然后传给NSString
2、如果是一个 NSString 的 *sourceStr 赋值给str,copy和strong效果一样
3、赋值string应该用self.xxx,如果直接用_xxx,copy属性无效,等同于strong效果

赋值NSString

赋值NSString无论是用的Copy还是strong都是浅拷贝。

@interface ViewController ()

@property (nonatomic, strong) NSString *strongString;
@property (nonatomic, copy) NSString *copyedString;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    NSString *string = @"abc";
    self.strongString = string;
    self.copyedString = string;
    NSLog(@"origin string: %p, %p", string, &string);
    NSLog(@"strong string: %p, %p", _strongString, &_strongString);
    NSLog(@"copy   string: %p, %p", _copyedString, &_copyedString);

    //输出  origin string: 0x1003a4e08, 0x16fa67e48
    //输出  strong string: 0x1003a4e08, 0x111e1ec00
    //输出  copy   string: 0x1003a4e08, 0x111e1ec08
}
@end
赋值NSMutableString

赋值NSMutableString用的Copy进行深复制。strong是浅复制
可以看到下面改变源string,strongString的值变为和源string一样,指向同一个内存单元。
而copyedString进行了深复制,不随string改变。

NSMutableString *string = [NSMutableString stringWithString:@"origin"];
self.strongString = string;
self.copyedString = string;
[string appendString:@"_append"];

NSLog(@"origin string: %p, %p, %@", string, &string, string);
NSLog(@"strong string: %p, %p, %@", _strongString, &_strongString, _strongString);
NSLog(@"copy   string: %p, %p, %@", _copyedString, &_copyedString, _copyedString);

//输出  origin string: 0x1c04515b0, 0x16f6dfe48, origin_append
//输出  strong string: 0x1c04515b0, 0x11fd09f00, origin_append
//输出  copy   string: 0xa006e696769726f6, 0x11fd09f08, origin
注意使用_.xxx赋值copy属性无效

可以看到下面改变源string,strongString和copyedString为和源string一样,3个都指向同一个内存单元。

NSMutableString *string = [NSMutableString stringWithString:@"origin"];
_strongString = string;
_copyedString = string;
[string appendString:@"_append"];

NSLog(@"origin string: %p, %p, %@", string, &string, string);
NSLog(@"strong string: %p, %p, %@", _strongString, &_strongString, _strongString);
NSLog(@"copy   string: %p, %p, %@", _copyedString, &_copyedString, _copyedString);

//输出  origin string: 0x1c02586f0, 0x16f407e48, origin_append
//输出  strong string: 0x1c02586f0, 0x1011166f0, origin_append
//输出  copy   string: 0x1c02586f0, 0x1011166f8, origin_append
赋值NSMutableArray
@interface ViewController ()

@property (nonatomic, strong) NSArray *strongArray;
@property (nonatomic, copy) NSArray *copyedArray;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    NSMutableArray *originArray = [NSMutableArray arrayWithObjects: @"a", @"b", @"c", nil];
    self.strongArray = originArray;
    self.copyedArray = originArray;

    [originArray addObject:@"d"];

    NSLog(@"origin Array %p  %p   %ld", originArray, &originArray, originArray.count);
    NSLog(@"strong Array %p  %p   %ld", _strongArray, &_strongArray, _strongArray.count);
    NSLog(@"copyed Array %p  %p   %ld", _copyedArray, &_copyedArray, _copyedArray.count);

    //输出  origin Array 0x1c4458930  0x16f1e7e48   4
    //输出  strong Array 0x1c4458930  0x1012299d0   4
    //输出  copyed Array 0x1c44589c0  0x1012299d8   3
}
@end

总的来说,A属性加入copy关键字是作用是:如果将可变的外部变量B赋值给A时,将B进行深复制传给A,使得B改变时不影响A的值。

自定义对象Copy

需要实现NSCopying协议能使用Copy方法

//Test.h
#import <Foundation/Foundation.h>

@interface Test : NSObject<NSCopying>
@property (nonatomic, assign) int index;

@end


//Test.m
#import "Test.h"

@implementation Test

- (instancetype)copyWithZone:(NSZone *)zone {
    Test *copy = [Test allocWithZone:zone];
    copy.index = _index;//拷贝数据
    return copy;
}

@end

直接赋值是指针赋值,指向同一个对象(内存单元),改变一个另外一个也变

Test *test1 = [Test new];
test1.index = 5;
Test *test2 = test1;

test2.index = 6;
NSLog(@"test1: %p %d", test1, test1.index);
NSLog(@"test2: %p %d", test2, test2.index);

test1.index = 7;
NSLog(@"test1: %p %d", test1, test1.index);
NSLog(@"test2: %p %d", test2, test2.index);

// 输出 test1: 0x1c000d4b0 6
// 输出 test2: 0x1c000d4b0 6
// 输出 test1: 0x1c000d4b0 7
// 输出 test2: 0x1c000d4b0 7

copy方法进行深复制 改变其中一个不影响另外一个

Test *test1 = [Test new];
test1.index = 5;
Test *test2 = [test1 copy];

test2.index = 6;
NSLog(@"test1: %p %d", test1, test1.index);
NSLog(@"test2: %p %d", test2, test2.index);

test1.index = 7;
NSLog(@"test1: %p %d", test1, test1.index);
NSLog(@"test2: %p %d", test2, test2.index);

// 输出 test1: 0x1c401ef30 5
// 输出 test2: 0x1c401f060 6
// 输出 test1: 0x1c401ef30 7
// 输出 test2: 0x1c401f060 6

使用copy属性关键字

#import "Test.h"

@interface ViewController ()
@property (nonatomic, copy) Test *copyedTest;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    Test *orignTest = [Test new];
    orignTest.index = 5;
    self.copyedTest = orignTest;

    _copyedTest.index = 6;
    NSLog(@"orignTest:  %p %d", orignTest, orignTest.index);
    NSLog(@"copyedTest: %p %d", _copyedTest, _copyedTest.index);

    orignTest.index = 7;
    NSLog(@"orignTest:  %p %d", orignTest, orignTest.index);
    NSLog(@"copyedTest: %p %d", _copyedTest, _copyedTest.index);

    // 输出 orignTest:  0x1c40165d0 5
    // 输出 copyedTest: 0x1c4016610 6
    // 输出 orignTest:  0x1c40165d0 7
    // 输出 copyedTest: 0x1c4016610 6
}
@end
利用归档实现深复制

需要实现NSCoding协议

//Test.h
#import <Foundation/Foundation.h>
@interface Test : NSObject<NSCoding>
@property (nonatomic, assign) int index;
@end

//Test.m
#import "Test.h"

@implementation Test

- (void)encodeWithCoder:(NSCoder *)encoder {
    [encoder encodeObject:[NSNumber numberWithInt:self.index] forKey:@"index"];
}

- (instancetype)initWithCoder:(NSCoder *)decoder {
    self.index = [[decoder decodeObjectForKey:@"index"] intValue];
    return self;
}

@end
Test *test1 = [Test new];
test1.index = 5;

NSData *data = [NSKeyedArchiver archivedDataWithRootObject:test1];//归档
Test *test2 = [NSKeyedUnarchiver unarchiveObjectWithData:data];

test2.index = 6;
NSLog(@"test1: %p %d", test1, test1.index);
NSLog(@"test2: %p %d", test2, test2.index);

test1.index = 7;
NSLog(@"test1: %p %d", test1, test1.index);
NSLog(@"test2: %p %d", test2, test2.index);

// 输出 test1: 0x1c400c370 5
// 输出 test2: 0x1c8009870 6
// 输出 test1: 0x1c400c370 7
// 输出 test2: 0x1c8009870 6
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值