一文明白strong,weak,assign|一文明白strong,weak,assign, copy, retain,有源码
我们在项目中经常声明属性,属性的引用类型修饰符有strong,weak,assign, copy, retain,它们分别有何含义呢?我们来做一次总结。
由于iOS的内存管理机制是引用计数管理,也就是说当一个对象创建的时候,引用计数为1,当对这个对象进行copy操作的时候,引用计数会加1,当不需要使用这个对象的时候,系统会进行release操作,引用计数减1,当引用计数为0的时候,系统就会把这个对象释放掉。
- strong:当使用strong修饰一个指针的时候,这个指针是一个强引用类型,当它指向一个对象的时候,这个对象的引用计数会加1 。
- weak: 当使用weak修饰一个指针的时候,这个指针是一个弱引用类型,当它指向一个对象的时候,这个对象的引用计数并不会加1 。
- assign: 对于值类型而言,声明的时候使用assign进行修饰。
- copy: 对于不可变类型,copy修饰的指针是浅拷贝,指向的内存地址引用计数加1,当copy修饰的指针值改变的时候,地址也会改变,原来指向的地址的引用计数减1.对于可变类型而言,copy修饰的指针是深拷贝,把指向的对象的值拷贝一份。
- retain: 是MRC遗留下来的修饰符,目前和strong一样,修饰的属性指向的地址引用计数加1 ,在ARC下,我们不常使用这个修饰符。
文章图片
image.png
文章图片
image.png 对于也不喜欢看图的童鞋,来来来,上代码:
//
//ViewController.m
//Test
//
//Created by wenhuanhuan on 2020/6/17.
//Copyright ? 2020 weiman. All rights reserved.
//#import "ViewController.h"@interface ViewController ()@property(nonatomic, strong)NSString * sA;
@property(nonatomic, weak)NSString * wA;
@property(nonatomic, copy)NSString * cA;
@property(nonatomic, retain)NSString * rA;
@property(nonatomic, strong)NSArray * sArr;
@property(nonatomic, weak)NSArray * wArr;
@property(nonatomic, copy)NSArray * cArr;
@property(nonatomic, retain)NSArray * rArr;
@property(nonatomic, weak)NSSet * wSet;
@property(nonatomic, assign)NSSet * aSet;
@end@implementation ViewController- (void)viewDidLoad {
[super viewDidLoad];
[self test_p];
[self test_a];
}-(void)test_a {
@autoreleasepool {
NSSet * set = [NSSet setWithObjects:@"1", @"2", @"3", nil];
[self printWithObj:set mark:@"set"];
//retainCount: 1
self.wSet = set;
[self printWithObj:set mark:@"set weak"];
//retainCount: 1
self.aSet = set;
[self printWithObj:set mark:@"set assign"];
//retainCount: 1set = [NSSet setWithObjects:@"6", @"8", @"5", nil];
[self printWithObj:set mark:@"set change"];
}NSLog(@"self.wSet = %p%@", self.wSet, self.wSet);
//由于set已经释放了,self.aSet变成了野指针,访问野指针崩溃
// NSLog(@"self.aSet = %p%@", self.aSet, self.aSet);
}-(void)test_p {NSLog(@"-------非集合,不可变类型---NSString------------\n");
/**
对于NSString类型,苹果做了优化,retainCount值为-1
*/
NSString * sA1 = @"小莉莉";
[self printWithObj:sA1 mark:@"NSString test1"];
NSString * sA2 = [[NSString alloc]init];
[self printWithObj:sA2 mark:@"NSString test2"];
printf("\n\n");
//使用如下方法创建的NSString对象,retainCount值为1
NSString * str = [[NSString alloc] initWithUTF8String:"小红花"];
[self printWithObj:str mark:@"NSString test3"];
//retainCount = 1
self.sA = str;
[self printWithObj:str mark:@"NSString test4"];
//retainCount = 2
self.wA = str;
[self printWithObj:str mark:@"NSString test5"];
//retainCount = 2
self.cA = str;
[self printWithObj:str mark:@"NSString test6"];
//retainCount = 3
self.cA = @"copy";
[self printWithObj:str mark:@"NSString test7"];
//retainCount = 2
self.rA = str;
[self printWithObj:str mark:@"NSString test8"];
//retainCount = 3printf("\n\n");
NSLog(@"-------非集合,可变类型---NSMutableString------------\n");
NSMutableString * mStr = [[NSMutableString alloc]initWithString:@"可变字符串"];
[self printWithObj:mStr mark:@"NSMutableString test1"];
//retainCount = 1
self.sA = mStr;
[self printWithObj:mStr mark:@"NSMutableString test2"];
//retainCount = 2
self.wA = mStr;
[self printWithObj:mStr mark:@"NSMutableString test3"];
//retainCount = 2
self.cA = mStr;
[self printWithObj:mStr mark:@"NSMutableString test4"];
//retainCount = 2
self.rA = mStr;
[self printWithObj:mStr mark:@"NSMutableString test5"];
//retainCount = 3
[self printWithObj:self.sA mark:@"sA"];
[self printWithObj:self.cA mark:@"cA"];
printf("\n\n");
NSLog(@"-------集合,不可变类型---NSArray------------\n");
NSArray * arr = @[@1,@2];
[self printWithObj:arr mark:@"NSArray test1"];
//retainCount = 1
self.sArr = arr;
[self printWithObj:arr mark:@"NSArray test2"];
//retainCount = 2
self.wArr = arr;
[self printWithObj:arr mark:@"NSArray test3"];
//retainCount = 2
self.cArr = arr;
[self printWithObj:arr mark:@"NSArray test4"];
//retainCount = 3
self.cArr = @[@5, @6];
[self printWithObj:arr mark:@"NSArray test4"];
//retainCount = 2
self.rArr = arr;
[self printWithObj:arr mark:@"NSArray test5"];
//retainCount = 3printf("\n\n");
NSLog(@"-------集合,可变类型---NSMutableArray------------\n");
NSMutableArray * mArr = [NSMutableArray arrayWithObjects:@"a",@"b", nil];
[self printWithObj:mArr mark:@"NSMutableArray test1"];
//retainCount = 1
self.sArr = mArr;
[self printWithObj:mArr mark:@"NSMutableArray test1"];
//retainCount = 2
self.wArr = mArr;
[self printWithObj:mArr mark:@"NSMutableArray test1"];
//retainCount = 2
self.cArr = mArr;
[self printWithObj:mArr mark:@"NSMutableArray test1"];
//retainCount = 2
self.cArr = @[@"iii"];
[self printWithObj:mArr mark:@"NSMutableArray test1"];
//retainCount = 2
self.rArr = mArr;
[self printWithObj:mArr mark:@"NSMutableArray test1"];
//retainCount = 3
}-(void)printWithObj: (id)obj mark: (NSString *)str {
NSLog(@"%@ 值:%@, 地址: %p, retainCount: %ld", str, obj, obj, (unsigned long)[obj retainCount]);
}
@end
总结
在MRC时代,关于属性引用计数的修饰符是retain, copy, assign,在ARC时代,引入了strong和weak。【一文明白strong,weak,assign|一文明白strong,weak,assign, copy, retain,有源码】打印结果:
strong:强引用,引用计数增加;
weak:弱引用,引用计数不增加;
assign:修饰值类型,修饰对象的时候,类似于weak,引用计数不增加。但是当对象释放的时候,assign指针不会释放,造成野指针,再次访问,会崩溃,而weak则不会崩溃。
retain:MRC下遗留的修饰符,引用计数会增加,类似于strong,ARC下,我们不常使用。
copy:对于不可变类型,copy修饰的指针是浅拷贝,指向的内存地址引用计数加1,当copy修饰的指针值改变的时候,地址也会改变,原来指向的地址的引用计数减1。对于可变类型而言,copy修饰的指针是深拷贝,把指向的对象的值拷贝一份。
2020-06-21 17:19:34.926294+0800 Test[2573:170127] -------非集合,不可变类型---NSString------------2020-06-21 17:19:34.926497+0800 Test[2573:170127] NSString test1 值:小莉莉, 地址: 0x107ee01d8, retainCount: -1
2020-06-21 17:19:34.926634+0800 Test[2573:170127] NSString test2 值:, 地址: 0x7fff80971d08, retainCount: -12020-06-21 17:19:34.926823+0800 Test[2573:170127] NSString test3 值:小红花, 地址: 0x60000332af20, retainCount: 1
2020-06-21 17:19:34.926944+0800 Test[2573:170127] NSString test4 值:小红花, 地址: 0x60000332af20, retainCount: 2
2020-06-21 17:19:34.927091+0800 Test[2573:170127] NSString test5 值:小红花, 地址: 0x60000332af20, retainCount: 2
2020-06-21 17:19:34.927214+0800 Test[2573:170127] NSString test6 值:小红花, 地址: 0x60000332af20, retainCount: 3
2020-06-21 17:19:34.927340+0800 Test[2573:170127] NSString test7 值:小红花, 地址: 0x60000332af20, retainCount: 2
2020-06-21 17:19:34.927552+0800 Test[2573:170127] NSString test8 值:小红花, 地址: 0x60000332af20, retainCount: 32020-06-21 17:19:34.927868+0800 Test[2573:170127] -------非集合,可变类型---NSMutableString------------2020-06-21 17:19:34.928174+0800 Test[2573:170127] NSMutableString test1 值:可变字符串, 地址: 0x600003d37420, retainCount: 1
2020-06-21 17:19:34.928456+0800 Test[2573:170127] NSMutableString test2 值:可变字符串, 地址: 0x600003d37420, retainCount: 2
2020-06-21 17:19:34.928759+0800 Test[2573:170127] NSMutableString test3 值:可变字符串, 地址: 0x600003d37420, retainCount: 2
2020-06-21 17:19:34.929087+0800 Test[2573:170127] NSMutableString test4 值:可变字符串, 地址: 0x600003d37420, retainCount: 2
2020-06-21 17:19:34.935395+0800 Test[2573:170127] NSMutableString test5 值:可变字符串, 地址: 0x600003d37420, retainCount: 3
2020-06-21 17:19:34.935553+0800 Test[2573:170127] sA 值:可变字符串, 地址: 0x600003d37420, retainCount: 3
2020-06-21 17:19:34.935701+0800 Test[2573:170127] cA 值:可变字符串, 地址: 0x600003d33c60, retainCount: 12020-06-21 17:19:34.935822+0800 Test[2573:170127] -------集合,不可变类型---NSArray------------2020-06-21 17:19:34.936007+0800 Test[2573:170127] NSArray test1 值:(
1,
2
), 地址: 0x6000033258e0, retainCount: 1
2020-06-21 17:19:34.936148+0800 Test[2573:170127] NSArray test2 值:(
1,
2
), 地址: 0x6000033258e0, retainCount: 2
2020-06-21 17:19:34.936287+0800 Test[2573:170127] NSArray test3 值:(
1,
2
), 地址: 0x6000033258e0, retainCount: 2
2020-06-21 17:19:34.936424+0800 Test[2573:170127] NSArray test4 值:(
1,
2
), 地址: 0x6000033258e0, retainCount: 3
2020-06-21 17:19:34.936564+0800 Test[2573:170127] NSArray test4 值:(
1,
2
), 地址: 0x6000033258e0, retainCount: 2
2020-06-21 17:19:34.936717+0800 Test[2573:170127] NSArray test5 值:(
1,
2
), 地址: 0x6000033258e0, retainCount: 32020-06-21 17:19:34.936843+0800 Test[2573:170127] -------集合,可变类型---NSMutableArray------------2020-06-21 17:19:34.936990+0800 Test[2573:170127] NSMutableArray test1 值:(
a,
b
), 地址: 0x600003d37690, retainCount: 1
2020-06-21 17:19:34.937306+0800 Test[2573:170127] NSMutableArray test1 值:(
a,
b
), 地址: 0x600003d37690, retainCount: 2
2020-06-21 17:19:34.937627+0800 Test[2573:170127] NSMutableArray test1 值:(
a,
b
), 地址: 0x600003d37690, retainCount: 2
2020-06-21 17:19:34.937942+0800 Test[2573:170127] NSMutableArray test1 值:(
a,
b
), 地址: 0x600003d37690, retainCount: 2
2020-06-21 17:19:34.938245+0800 Test[2573:170127] NSMutableArray test1 值:(
a,
b
), 地址: 0x600003d37690, retainCount: 2
2020-06-21 17:19:34.938527+0800 Test[2573:170127] NSMutableArray test1 值:(
a,
b
), 地址: 0x600003d37690, retainCount: 3
2020-06-21 17:19:34.938856+0800 Test[2573:170127] set 值:{(
1,
2,
3
)}, 地址: 0x600003d38840, retainCount: 1
2020-06-21 17:19:34.939117+0800 Test[2573:170127] set weak 值:{(
1,
2,
3
)}, 地址: 0x600003d38840, retainCount: 1
2020-06-21 17:19:34.939376+0800 Test[2573:170127] set assign 值:{(
1,
2,
3
)}, 地址: 0x600003d38840, retainCount: 1
2020-06-21 17:19:34.939715+0800 Test[2573:170127] set change 值:{(
6,
8,
5
)}, 地址: 0x600003d376f0, retainCount: 1
2020-06-21 17:19:34.939985+0800 Test[2573:170127] self.wSet = 0x0(null)
推荐阅读
- 多想你明白我的心意
- 这些你能看明白吗()
- 一个安排明白的交作业小指南
- (If)|(If) 404 Not Found
- 屁股决定脑袋!当了领导后才明白的8件事,每一个都是经验和教训
- mysql|一文深入理解mysql
- 数据技术|一文了解Gauss数据库(开发历程、OLTP&OLAP特点、行式&列式存储,及与Oracle和AWS对比)
- 明白对你来说最重要的是什么
- 一文弄懂MySQL中redo|一文弄懂MySQL中redo log与binlog的区别
- c语言|一文搞懂栈(stack)、堆(heap)、单片机裸机内存管理malloc