内存管理小结

2018-02-28  本文已影响14人  hiseason

一、基础知识

1. property

@property 作用是声明属性,也就是快速方便为实例变量创建存取器(accessor),并允许我们用点语法使用存取器,它代表一个表现对象的指针。assign,retain,strong,weak,还有copy,这些都是一个property在声明中可以指定的属性,这些属性的不同之处就在于这个指针。
Objective-C中的@property

存取器(accessor) 用于获取和赋值实例变量的方法,即get 和 set 方法。

2. self. 和下划线的区别

  1. self. 是调用属性(对象),会调用 get 和 set 方法, _xx只是调用变量
    例如对一个数值实现了懒加载, 那在之后的调用中必须用 self. ,而不可以用下划线
  2. self.调用系统的 get,set 方法的步骤: 如果用户自定义了 get 和 set 方法, 则不会再生成. 如果用户没有自定义, 系统才会自动生成。(在 ios5之前, 属性声明需要@synthesize指令告诉编译器帮助生成 get 和 set 方法, ios5之后系统会自动生成 )
  3. self. 会使引用计数器+1, 而_xx 不会
  4. self. 可以获取到父类的属性
  5. _xx 忽略了 self 指针, 容易在 block 中造成循环引用(weakSelf)
    最后总结:self方法实际上是用了get和set方法间接调用,下划线方法是直接对变量操作。
//以前马虎犯的错误, 导致自动计算行高一直错误, 界面混乱
- (void)setBaskModel:(BaskModel *)baskModel{
    self.baskModel = baskModel;❌ 
    _baskModel = baskModel;
}

3.引用计数器

  1. 为什么引入引用计数器的概念?
    如果没有引用计数器, 默认在一个代码块中执行完毕就会释放对象, 那在其他方法中再想调用此对象就调用不到了. 所以引入引用计数器的概念。
  2. 规则: 当引用计数器为0时, 对象会被释放。
    alloc init方法,默认计数器值(retainCount)为1;
    retain方法, 计数器值+1;
    release 方法, 计数器值-1;
    alloc:为一个新对象分配内存,并且它的引用计数为1。调用alloc方法,你便有对新对象的所有权
    copy:制造一个对象的副本,该副本的 引用计数为1,调用者具有对副本的所有权
    retain:使对象的引用计数加1,并且获得对象的所有权
  3. ARC 是如何引用引用计数器的?
    ARC的内存管理,是编译器在编译时自动添加retain,release,autorelease

二、 strong&weak、copy和assign 的比较

1. strong

用于 oc 对象类型(NSArray、NSDate、NSNumber、模型类)

2.weak

用于 UI控件,delegate

对比
strong类型的指针就是像是拴住的狗,只要你用绳子拴住狗,那么狗就不会跑掉。如果有5个人都牵着这一条狗(5条绳子牵一只狗),类比为5个strong类型指针指向一个对象。除非5个绳子都脱落,否则狗是不会跑掉的,类比,5个strong指针都=nil,则该对象释放。
weak型指针就像是一个小孩子指着狗喊道:“看,有一只狗在那里”,只要狗一直被拴着,那么小孩子就能看到狗 (weak指针)会一直指向它,只要狗的绳子脱落,那么狗就会跑掉,不管有多少的小孩在看着它。

3.assign

用于非OC对象类型,‘基本数据类型’、‘枚举’、‘结构体’ 等,这些数值主要存在于栈上,系统自动管理。

4.copy

用在修饰有可变对应类型的不可变对象上,如NSString, NSArray, NSDictionary。
NSMutableString 用 strong, 因为 mutableString 之后还要进行改变

//如果用 strong的话,看一下
NSString *text1 = @“oldText”;
NSString *text2 = text1;
text2 = @“newText”; //用 strong 的话 text1 也是@“newText”

小结

对比.png

weak 修饰的变量指向的内存如果被释放, 则会自动指向 nil, 因为响应 delegate 的vc 可能已经被释放了, delegate 指向的内存空间就会释放, 用 weak 才不会导致野指针错误.


delegate.png

从sb中拖线出来的UI控件必然会被其在SB中的父控件以addSubview方法或其他方法强引用,[self.view addSubview: label];如果我们在控制器或者其父控件中再定义一个strong的属性来指向它的话File's owner,该UI控件的引用计数器会被两次+1,如此这般当其控制器或者父控件被回收的时候,该UI控件无法销毁,造成内存泄露。

IBOutlet.png

如果我们创建了一个对象,但是却没有另一个对象对他进行强引用,那么我们所创建的那个对象,会在创建完成后立即被销毁,所以代码声明的subview 一般用strong。


代码声明的subview.png

assign,weak,retain,strong,copy属性浅谈

上一篇 下一篇

猜你喜欢

热点阅读