修饰词:assign、weak、strong、retain、copy、nonatomic、atomic、readonly、readwrite
assign(ARC、MRC)
- 修饰整型等基本数据类型,直接赋值的意思。
- 如果没有weak、strong、retain、copy修饰,默认使用assign。
- 对象也可以用assign修饰,只是引用计数不会+1(与strong的区别)
- 如果用来修饰对象属性,对象销毁后是不会指向nil的,就会产生野指针错误。(与weak的区别)
weak(ARC)(对象)
- 针对对象的修饰词,不能修饰基本数据类型(int float)
- weak修饰的引用计数不会+1,也是直接赋值
- 弱引用是为了打破循环引用而产生的。
- 指针指向的对象如果被销毁,指针会指向nil,不会产生野指针错误。
在block中,block在copy的时候,会对内部使用到的对象引用计数+1,,如果使用[self 方法名],那么就会有一个强指针指向self所在的class的内存地址,class的引用计数+1,这样导致class所在的内存地址无法被释放,造成内存泄露
assign和weak区别:weak比assign多了一个功能。就是当属性所指向的对象消失的时候(也就是内存引用计数为0)会自动赋值为nil,这样再向weak修饰的属性发送消息就不会导致野指针操作crash。
举个例子:
//
// ViewController.m
// weak与assgin的区别
//
// Created by 王海玉 on 2017/10/14.
// Copyright © 2017年 王海玉. All rights reserved.
//
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic,weak) id weakPoint;
@property (nonatomic,assign) id assignPoint;
@property (nonatomic,strong) id strongPoint;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.strongPoint = [NSDate date];
NSLog(@"strong属性:%@",self.strongPoint);
self.weakPoint = self.strongPoint;
self.assignPoint = self.strongPoint;
self.strongPoint = nil;
NSLog(@"weak属性:%@",self.weakPoint);
// NSLog(@"assign属性:%@",self.assignPoint)
}
@end
当注释打开时,程序就有可能会崩溃。(需要多运行几次)
retain ( MRC )
- release 旧对象( 旧对象计数器 -1 ) , retain 新对象( 新对象计数器 +1 ) , 然后指向新对象 .
- 在set方法里面是这样的 :
if(_dog!=nil) {
[_dog release];
}
_dog= [dog retain];
strong ( ARC )(对象)
- 直接赋值并且对象的引用计数器 +1 .
- 在 ARC 里替代了 retain 的作用 .
- 直接指向该指针
copy ( ARC/MRC )
- copy 在 MRC 时是这样做的 release 旧对象( 旧对象的引用计数器 -1 ) , copy 新对象( 新对象的引用计数器 +1 ) , 然后指向新对象 .(新对象是指最终指向的那个对象,不管深拷贝还是浅拷贝)
- copy 在 ARC 时是这么干的 copy 新对象( 新对象的引用计数器 +1 ) , 然后指向新对象 .
copy和mutableCopy区别
举例:
NSString *test1 =@"123456";
// NSArray *array1 =[NSArray arrayWithObjects:@"123",@"123",@"123",nil];
NSString *test2 =[test1 copy];
NSString *test3 =[test1 mutableCopy];
NSMutableString *test4 =[test1 copy];
NSMutableString *test5 =[test1 mutableCopy];
//test1 = @"asda";
NSLog(@"地址1 %d 地址2 %d",test1,test2);
NSLog(@"地址1 %d 地址2 %d",test1,test3);
NSLog(@"地址1 %d 地址2 %d",test1,test4);
NSLog(@"地址1 %d 地址2 %d",test1,test5);
运行结果
NSString *test1 =@"123456";
NSArray *test2 =[array1 copy];
NSArray *test3 =[array1 mutableCopy];
NSMutableArray *test4 =[array1 copy];
NSMutableArray *test5 =[array1 mutableCopy];
NSLog(@"地址1 %d 地址2 %d",array1,test2);
NSLog(@"地址1 %d 地址2 %d",array1,test3);
NSLog(@"地址1 %d 地址2 %d",array1,test4);
NSLog(@"地址1 %d 地址2 %d",array1,test5);
运行结果
那么看来对NSString 和 NSArray来讲 copy都是浅copy,NSMutableCopy则是深度copy;
那么如果被copy的对象是可变的呢?
NSString *test1 = [NSMutableString stringWithFormat:@"123"];
//将第一行代码改成如下;
运行结果
则可以产生一个一样的结论,copy对可变字符串是深拷贝,而NSMutableCopy则对所有都是深度copy。
strong copy mutableCopy 区别
image.png
nonatomic ( ARC/MRC )
- 不对set方法加同步锁 .
- 性能好
- 线程不安全
非多线程时用效率高。
atomic ( ARC/MRC )
1.原子属性就是对生成的 set 方法加互斥@synchronized(锁对象) .
@synchronized(self) { _delegate = delegate;}
2.需要消耗系统资源 .
3.互斥锁是利用线程同步实现的 , 意在保证同一时间只有一个线程调用 set 方法 .
4.其实还有 get 方法 , 要是同时 set 和 get 一起调用还是会有问题的 . 所以即使用了 atomic 修饰 还是不够安全 .