iOS属性修饰符copy

正文

  iOS开发中,对于NSString,NSDictionary,NSArray一般都会使用copy来进行修饰,其实用strong的话也没有问题。只是copy修饰在进行赋值时会进行内存的拷贝,相当于赋值之后和被赋值的对象指向不同的内存地址。这样做的好处是防止修改了被赋值对象(等号右边)导致了等号左边的属性发生变化。

  当然如果属性本身是对外不可见的,怎么修改都放在.m文件中,这样外界就无法修改类的属性,类的属性只受内部控制,这样可以使用strong来修饰,不过也只是降低了被修改的风险而已。

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
30
31
@property (nonatomic, strong) SJPAnimationViewController *vc;
@property (nonatomic, copy) NSString *str;
@property (nonatomic, copy) NSDictionary *dict;
@property (nonatomic, copy) NSArray *arr;
//@property (nonatomic, strong) NSString *str;
//@property (nonatomic, strong) NSDictionary *dict;
//@property (nonatomic, strong) NSArray *arr;
@end

@implementation SJPTabBarController

- (void)viewDidLoad {
[super viewDidLoad];
[self initTabBarVc];
NSMutableString *mStr = [NSMutableString stringWithString:@"123"];
NSMutableDictionary *mDict = [NSMutableDictionary dictionaryWithDictionary:@{@"test1":@"123",@"test2":@"456"}];
NSMutableArray *mArr = [NSMutableArray arrayWithArray:@[@"1",@"2",@"3"]];
self.str = mStr;
self.dict = mDict;
self.arr = mArr;
/// 修改数据
mStr.string = @"12345";
[mDict removeObjectForKey:@"test1"];
[mArr removeObjectAtIndex:0];
NSLog(@"mstring 地址:@%p, 数据:@%@\n",mStr,mStr);
NSLog(@"string 地址:@%p, 数据:@%@\n\n\n",self.str,self.str);
NSLog(@"marray 地址:@%p, 数据@%@\n",mArr,mArr);
NSLog(@"array 地址:@%p, 数据@%@\n\n\n",self.arr,self.arr);
NSLog(@"mdict 地址:@%p, 数据:@%@\n",mDict,mDict);
NSLog(@"dict 地址:@%p, 数据:@%@\n",self.dict,self.dict);
}

  上图是demo代码,下图是表现结果.

picture1

  使用copy修饰的结果,修改了原数据,不会导致赋值之后的数据发生改变。因为指向了不同的地址。

picture2

  使用strong修饰的结果,修改了原数据,赋值之后的数据也发生了改变,因为指向了相同的地址。

picture3

  另外追加一点,为何nsstring的值给定之后可以重复修改,nsdictionary和nsarray值给定之后需要修改却不行。

  上面这个说法其实是错误的。并不是nssrting可以重复修改,只是string类型修改起来比较容易,重新赋值之后其实本身已经指向了新的内存地址。因此,nsdict和nsarray想要修改值要做的就是修改本身的内存地址,只不过内部可能包含更多数据,所以比起string来说更加繁琐。