1、属性修饰符
1、strong :强引用,只能用来修饰对象,属性的默认修饰符,其修饰的的对象引用计数加一
2、weak :弱饮用,只能用来修饰对象,修饰的对象引用计数不增加,可以避免循环引用,weak修饰的对象被释放后,指针会被置为nil,此时向对象发送消息不会崩溃
3、assign:可修饰对象和基本数据类型,其修饰的对象引用计数不增加,当对象被释放后,指针不会置为nil,这时就会产生野指针,此时向对象发送消息会崩溃。所以assign通常修饰基本数据类型,因为基本数据类型存储在栈区,先进先出,基本数据类型出栈后,assign修饰的变量就不存在了,不用担心指针问题。
4、copy:引用,修饰不可变的对象,比如(NSString、NSArray、NSADictionary)。copy和strong类似,不同之处在于,copy修饰的对象会现在内存中拷贝一个新的对象,copy会指向那个新对象的内存地址,这样避免了多个指针指向同一个对象时,其中一个指针改变了对象,其余指针指向的对象也跟着改变。
5、nonatomic和atomic的区别 atomic系统会自动生成get和set方法,会保证get和set方法的完整性,保证可以获取到一个完整的对象,nonatomic的存取速度要比atomic快。
堆和栈
iOS中什么情况下会使用内存
①创建一个对象 ②定义一个变量 ③调用一个方法
管理方式
栈:
①由编译器自动管理,无需手动释放内存
②存放局部变量、函数的参数
③有动态分配和静态分配两种
动态分配: 通过alloc函数进行分配
静态分配: 如局部变量
④栈使用的是一级缓存, 他们通常都是被调用时处于存储空间中,调用完毕立即释放
什么是栈溢出:栈溢出就是缓冲区溢出的一种。程序在运行过程中,为了临时存取数据的需要,一般都要分配一些内存空间,通常称这些空间为缓冲区。如果向缓冲区中写入超过其本身长度的数据,以致于缓冲区无法容纳,就会造成缓冲区以外的存储单元被改写,这种现象就称为缓冲区溢出。
- iOS上主线程栈空间大小为1MB
- iOS上子线程栈空间大小为512KB
哪些情况会造成栈溢出
- 栈上变量直接分配内存长度超过栈空间大小,比如:int buf[1024*1024] = {0};
- 无线递归
堆:
①由程序员自己管理,需要手动释放内存(只不过现如今的系统自动做了这件事,我们称之为ARC)
②存储oc中的对象、成员变量
③动态分配内存空间
④堆则是存放在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定(并不是一旦成为孤儿对象就能被回收)。所以调用这些对象的速度要相对来得低一些。
2、runloop和线程、autolesaePool之间的关系
线程与runloop之间的关系:每一个线程,包括主线程,都会拥有一个专属的 NSRunLoop 对象,并且会在有需要的时候自动创建
每当一个app启动时会创建一个默认线程(即主线程),主线程的runloop会自动注册两个observe观察者
第一个observe会观察enter事件,当有enter事件时(即进入runloop),会调用_objc_autoreleasePoolPush()创建自动释放池
第二个observe会观察 两个事件,BeforeWaiting(准备进入睡眠) 和 Exit(即将退出Loop),Exit(即将退出Loop) 时调用 _objc_autorel