iOS内存管理

2022-04-09  本文已影响0人  Edviin_2de8
黄金法则

凡是通过alloc、init、copy、mutableCopy、retain进行创建的对象,都要使用release或autorelease进行释放。

Strong

强引用,持有对象,对象的retainCount+1。当对象没有Strong指向时,将会被释放。
声明对象时,默认Strong

@property (strong, nonatomic) UIWindow * window;

NSString类型的属性,最终可能指向的是NSMutableString,为了防止源字符串的修改引起变化,最好是采用copy来修饰

##用在可变字符串时是深拷贝:##
//属性是iOS管理变量数据存取的方法
@property (nonatomic, strong) NSString *name;
@property (nonatomic, copy) NSString *meng;
@end
@implementation ViewController
-(void)viewDidLoad {
    [super viewDidLoad];
    [self testCopyAndStrong];
    //[self testString];
}

-(void)testCopyAndStrong {
    NSMutableString *str = [[NSMutableString alloc] initWithString:@"meng"];
    self.meng = str;
    self.name = str;
    [str appendString:@"zhiqi"];
    //&打印指针的地址,没有&则是打印指针所指向对象的地址
    NSLog(@"%p, %p", str, &str);
    //strong特性,指针地址不同,但是指针所指向对象的地址相同,是浅拷贝(地址拷贝)
    NSLog(@"%p, %p", self.name, &_name); //copy特性,指针地址不同,指针所指向的对象的地址也不同,是深拷贝(内容拷贝)
    NSLog(@"%p, %p", self.meng, &_meng);
    NSLog(@"%@", str);
    //self.name打印出mengzhiqi,可见strong特性只是把指针所指向对象的地址拷贝了
    NSLog(@"%@", self.name);
    NSLog(@"%@", self.meng);
}
image.png
  • 对于不可变对象:strong和copy修饰,都是浅拷贝, 当对源数据修改时并无影响,用哪个都可以.
  • 对于可变对象:strong浅拷贝,copy深拷贝.
  • 如果不希望数据收到源数据的修改而影响就用copy.反之用strong
  • 对可变对象修饰:一定要用strong. 因为copy返回的是不可变对象.

weak

弱引用,不会引起引用计数的变化;当对象被释放时,所有指向对象的弱引用指针会被置为nil,防止野指针。
给nil发送消息时,会直接return,不会crash。

weak原理

对象的SideTable中有一个Weak表,以对象的内存地址为key,value为指向该对象的指针数组。
当对象销毁时,通过对象的内存地址找到所有弱引用的指针并且只为nil。

@property (nonatomic, weak, nullable) id <UITableViewDataSource> dataSource;
@property (nonatomic, weak, nullable) id <UITableViewDelegate> delegate;

assign

assign 纯粹指向对象,不会引起引用计数的变化,当对象被释放时,指针不会被置为nil,仍然指向原地址,容易造成野指针。
所以assign一般都用来指向基础类型的变量,例如 int float bool struct等值类型。
值类型会被放入栈中,遵循先进后出的原则,由系统维护
引用类型会被放入堆中,需要手动维护(MRC)或者ARC维护

深copy浅copy

深拷贝就是内容拷贝,浅拷贝就是指针拷贝。本质区别在于:

特点
Copy的目的是建立副本,同时修改原始对象和复本不会互相干扰
copy和mutableCopy存在的原因: 尽可能的节省内存开销.

  • 对于不可变类型的copy,为浅copy,对象引用计数+1。
  • 对可变类型的copy,为深copy,对象为不可变对象。\color{red}{这里不能对副本做增删修改.比如NSMutableArray.copy做删除操作会crash.}
    image.png
    -对对象做mutableCopy操作,都为深拷贝,拷贝对象也会变为可变类型。
    -对于容器类型(NSArray、NSDictionary等),深拷贝也仅是拷贝容器本身,对容器里面的元素只做浅拷贝。

自定义copy

atomic 与nonatomic

对atomic修饰的属性的setter、getter方法添加了原子锁,保证set、get操作的完整性,也就是下一次的set、get操作必须等到上一次的set、get操作完成之后才能执行。
因为atomic添加了原子锁,会增加开销,运行速度更慢,在不需要保证set、get操作的完整的情况下,所以一般都使用nonatomic。

atomic不能完全保证线程安全

只能保证set、get操作的完整性,当开启多个线程执行多个set、get操作时,无法保证执行的顺序。
另外如数组除了set、get操作外还有remove的操作。

ios其他关键字

nullable: 表示修饰的属性或参数可以为空
nonnull:非空,表示修饰的属性或参数不能为空
注意:nonnull,nullable只能修饰对象,不能修饰基本数据类型
null_resettable: get方法:不能返回为空,set方法可以为空
null_unspecified:不确定是否为空

上一篇 下一篇

猜你喜欢

热点阅读