iOS容易出错的知识
1. #import 跟#include 又什么区别,@class呢, #import<> 跟 #import””又什么区别?
答:#import是Objective-C导入头文件的关键字,#include是C/C++导入头文件的关键字,使用#import头文件会自动只导入一次,不会重复导入,相当于#include和#pragma once;@class告诉编译器某个类的声明,当执行时,才去查看类的实现文件,可以解决头文件的相互包含;#import<>用来包含系统的头文件,#import””用来包含用户头文件。
2. 原子(atomic)跟非原子(non-atomic)属性有什么区别?
答:atomic提供多线程安全。是防止在写未完成的时候被另外一个线程读取,造成数据错误
non-atomic:在自己管理内存的环境中,解析的访问器保留并自动释放返回的值,如果指定了 nonatomic ,那么访问器只是简单地返回这个值。
3.instancetype与id的区别
区别1:
在ARC(Auto Reference Count)环境下:
instancetype用来在编译期确定实例的类型,而使用id的话,编译器不检查类型, 运行时检查类型.
在MRC(Manual Reference Count)环境下:
instancetype和id一样,不做具体类型检查
区别2:
id可以作为方法的参数,但instancetype不可以
instancetype只适用于初始化方法和便利构造器的返回值类型
区别:
1>instancetype在类型表示上,跟id一样,可以表示任何对象类型
2>instancetype只能用在返回值类型上,不能像id一样用在参数类型上
3>instancetype比id多一个好处:编译器会检测instancetype的真实类型
4. weak 和 strong 区别
weak相当于老版本的assign,strong相当于retain
(weak和strong)不同的是 当一个对象不再有strong类型的指针指向它的时候 它会被释放 ,即使还有weak型指针指向它。
一旦最后一个strong型指针离去 ,这个对象将被释放,所有剩余的weak型指针都将被清除。
可能有个例子形容是妥当的。
想象我们的对象是一条狗,狗想要跑掉(被释放)。
strong型指针就像是栓住的狗。只要你用牵绳挂住狗,狗就不会跑掉。如果有5个人牵着一条狗(5个strong型指针指向1个对象),除非5个牵绳都脱落 ,否着狗是不会跑掉的。
weak型指针就像是一个小孩指着狗喊到:“看!一只狗在那” 只要狗一直被栓着,小孩就能看到狗,(weak指针)会一直指向它。只要狗的牵绳脱落,狗就会跑掉,不管有多少小孩在看着它。
只要最后一个strong型指针不再指向对象,那么对象就会被释放,同时所有的weak型指针都将会被清除。
5.友盟报错可以查到具体某一行的错误,原理是什么
错误分析是友盟为移动开发者提供的Crash收集和分析工具,帮助开发者监测App在移动设备上的运行状况,及时发现并解决错误,提升App的稳定性。
6. 深拷贝(内容拷贝) 浅拷贝(指针拷贝) 伪拷贝
原则: 看是否产生新的对象
例如:如果本身是一个不可变字符串
调用copy 方法 产生一个不可变字符串 此时和原来地址一样, 既指向同一个内存地址 没有产生新对象
调用mutableCopy 方法 产生一个可变字符串 由不可变 -> 可变 此时产生新的对象 所以是深拷贝
若本身是一个可变字符串
调用copy 方法 产生一个不可变字符串 此时和原来地址不一样, 既指向不同内存地址 产生新对象 既深拷贝
调用mutableCopy 方法 产生一个可变字符串 此时产生新的对象 所以是深拷贝
若此时是一个自定义的Person对象想实现拷贝, 内部实现如下:
先遵守 NSCopying 协议 --> 必须实现 copyWithZone: 的方法 ;
字符串为什么要用copy 而不用strong ?
若用strong: setter方法实现如下:
//- (void)setName:(NSString *)name { _name = name; }
此时改变其他对象会改变原来的属性,如这里的name, 也就是传什么就是什么
若用copy : setter方法实现如下:
//- (void)setName:(NSString *)name {_name = [name copy]; }//只会调copy 不会调mutableCopy 注意
相当于拷贝一份出来,不是同一个对象 不会影响原来的属性值
所有, 当你希望以后可以改变原来的就用strong , 反之, 取决于使用者,没有绝对的对错
面试: /** name属性值永远是不可变,所以定义为NSMutableString是不合理的 */
@property (nonatomic, copy) NSMutableString *name;
此时 setter是 {_name = [name copy]; } 是不可变的 而 你属性是可变, 别人会误以为是可变,容易把当可变用, 此时会崩溃, 所有此时不严谨
7. block 为什么要使用copy修饰
声明block的时候都是用copy来修饰
使用copy修饰的原因:
block本身是像对象一样可以retain,和release。但是,block在创建的时候,它的内存是分配在栈(stack)上,而不是在堆(heap)上。他本身的作于域是属于创建时候的作用域,一旦在创建时候的作用域外面调用block将导致程序崩溃。
使用retain也可以,但是block的retain行为默认是用copy的行为实现的,因为block变量默认是声明为栈变量的,为了能够在block的声明域外使用,所以要把block拷贝(copy)到堆,所以说为了block属性声明和实际的操作一致,最好声明为copy。
堆和栈的区别:
一、堆栈空间分配区别:
1、栈(操作系统):由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈;
2、堆(操作系统): 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,分配方式倒是类似于链表。
二、堆栈缓存方式区别:
1、栈使用的是一级缓存, 他们通常都是被调用时处于存储空间中,调用完毕立即释放;
2、堆是存放在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定(并不是一旦成为孤儿对象就能被回收)。所以调用这些对象的速度要相对来得低一些。
三、堆栈数据结构区别:
堆(数据结构):堆可以被看成是一棵树,如:堆排序;
栈(数据结构):一种先进后出的数据结构。
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。