uncategorized

NSString的copy和strong

最近在看一点Objective-C的东西的, 看到当声明一个NSString属性时, 通常有设置copy,
strong, 这两个有什么区别了. 开始以为copy的话会有对象在堆上面的一个拷贝, strong
只是对引用计数加1. 这个想法, 还是直接写代码验证比较好.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#import "ViewController.h"
#import <Foundation/Foundation.h>

@interface ViewController ()
@property (nonatomic, copy) NSString *stringCopy;
@property (nonatomic, strong) NSString *stringStrong;
@end

@implementation ViewController

- (void)viewDidLoad
{
[super viewDidLoad];
NSString* string = [NSString stringWithFormat:@"1"];
self.stringCopy = string;
self.stringStrong = string;

NSLog(@"string %p, %p, %@", string, &string, string);
NSLog(@"_stringCopy %p, %p, %@", _stringCopy, &_stringCopy, _stringCopy);
NSLog(@"_stringStrong %p, %p, %@", _stringStrong, &_stringStrong, _stringStrong);
}

- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

@end

下面是运行结果:

通过结果我们可以看到, 这三个是共享一个NSString实例的, 我用的明明是copy, 为什么没
有产生一个新的实例, 因为我们的NSString是一个不可变的实例, 所以编译器做了优化, 你
不可以对对它做改变, 所以copy一个新的NSString实例没有意义.

当我们把string的类型改成NSMutableString时, 在来看看运行的结果.

1
NSMutableString* string = [NSMutableString stringWithFormat:@"1"];

可以看出来, 当我们用可变对象后, copy约束就会产生一个新实例了.

在写上面的demo时, 我不写把属性给用错了, 出现了向下面的代码.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#import "ViewController.h"
#import <Foundation/Foundation.h>

@interface ViewController ()
@property (nonatomic, copy) NSString *stringCopy;
@property (nonatomic, strong) NSString *stringStrong;
@end

@implementation ViewController

- (void)viewDidLoad
{
[super viewDidLoad];
NSMutableString* string = [NSMutableString stringWithFormat:@"1"];
_stringCopy = string;
_stringStrong = string;

NSLog(@"string %p, %p, %@", string, &string, string);
NSLog(@"_stringCopy %p, %p, %@", _stringCopy, &_stringCopy, _stringCopy);
NSLog(@"_stringStrong %p, %p, %@", _stringStrong, &_stringStrong, _stringStrong);
}

- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

@end

我用属性stringCopy进行封装的实例__strongCopy进行赋值, 出现下面的运行结果, 虽然是
可变对象, 但出现地址相同的结果:

这个是什么情况, 不是copy吗, 没有出现我们想要的结果. 分析一下, 看出来了, 我们的st
ringCopy其实内部封装了一个setStringCopy方法, setStringCopy方法里面对实例变量
_stringCopy进行了操作, 而我在这里直接对_stringCopy进行复制, 直接指向了地址, 所以
出现了上面所以是可变对象和copy, 但还是出现地址相同的情况.

参考:
NSString属性什么时候用copy,什么时候用strong?