*Property属性
1)atomic
原子性,只有一个线程访问实例,线程安全(当前读取器),开销大,耗资源。
2)natomic
非原子性,线程不安全,可以被多个线程访问,效率高
3)assign(int, float) & weak & unsafe_unretained
a.修饰效果相同,不会改变引用计数,也不会改变旧数据的引用计数
b. assign:一般只修饰值类型,虽然可以修饰引用类型,但修饰对象释放后,指针不会置空,此时向对象发消息会奔溃
c. weak不会产生野指针的问题,修饰的对象被释放后,引用计数为0,指针置空,向对象发消息不会奔溃,weak是安全的。
d. ansafe_unretained只修饰对象
4)strong & retain & copy
a. 三者用于修饰引用类型
b. strong用于ARC,retain用于MRC
只要最后一个strong型指针不再指向对象,那么对象就会被释放,即使还有weak型指针指向它。一旦最后一个strong型指针离去 ,这个对象将被释放,所有剩余的weak型指针都将被清除。
c. copy分为深复制和浅复制。NSString,NSArray等不可变为浅复制,引用计数会+1,不会创建新的内存。
拷贝条件
iOS中并非所有的对象都支持copy和mutableCopy,只有遵循了NSCopy协议或者NSMutableCoy协议的类才行。如果遵循着两个协议就必须分别实现copyWithZone和mutableCopyZone方法
*沙盒
1)Documents:保存运用运行时生成的持久化数据,如游戏进度,绘图等信息,会被ITunes同步备份。
2)Library/Caches:保存运用运行时生成的持久化数据,ITunes不会同步备份,一般存储体积大,不需要备份等非重要数据,如缓存的图片,离线数据等。
3)tmp,保存运用等临时数据,内存不足及不运行时会被清除,不会备份
内存区域划分
1)栈区,由系统自动分配和释放,存放局部变量,容量小,速度快,有序。
2)堆,由程序员自己分配,不释放会出现内存泄漏,程序会回收内存,容量大,速度慢,无序。
3)静态存储区,存放全局变量和静态变量,程序结束时,系统回收。
4)常量区,存放常量,程序结束时,系统回收。
5)代码区,存放二进制代码。
Block为什么要用copy修饰
1)block创建时默认分配的内存是在栈栈上的,而不是在堆上,其本身的作用领域属于创建时候的作用域,一旦在作用域之外的内存调用就会导致程序奔溃,所以使用copy拷贝到堆上。
2)block创建在栈上,而block中的代码可能会用到本地的代码,只有将其拷贝到堆上,才能使用这些变量。
Block为什么不用retain修饰
retain修饰时增加引用计数器,block是存在栈上,可能随时会被系统回收
进入Block中的对象的引用计数器为什么会自动+1
block执行的是回调,因此block并不知道其中的对象创建后会在什么时候释放,为了不在block使用之前对象就已经被释放,所以block就增加一次使用对象的引用计数器
Block对于基本数据类型,会当作常量处理
int num1 = 10;
void (^block)() = ^{
NSlog(@"%d",num1); //
}
num1 = 20;
block();//输出10
//如果要修改进入block中的变量,则需加__block关键字
__block int num1 = 10;
void (^block)() = ^{
NSlog(@"%d",num1); //
}
num1 = 20;
block();//输出20
block中self的循环引用
block执行copy之后,block中使用self,此对象会被retain一次(注意:在堆区才起retain作用),会造成循环引用。
解决方式
在MRC下,用__block修饰
在ARC下,用unsafe_unretained 或者weak修饰
循环引用出现的几种情况
1)NSTimer
NSTimer对象timer作为对象A的属性,本意在A的dealloc中释放timer,但timer没有停止就不会触发dealloc,然后就互相等待,造成循环引用。
解决办法:显示调用timer的关闭方法[timer invaluale],再释放A对象
2)block块没有配合weak使用
3)delegate时用assign(MRC)或weak(ARC)
4)检查循环引用
Xcode -> Product -> Pofile -> Leaks
OC中的反射机制
1)class反射,通过类名字符串实例化对象
Class class = NSClassFromString(@“Student”);
Student *student = [[class alloc] init];
2)类名转化为字符串
Class class = [student class];
NSString *calssName = NSStringFromClass(class);
3)SEL的反射
SEL selector = =NSSelectorFromClass(@“setName”);
[stu performSelector:selector withObject:nil];
4)通过方法字符串形式实例化方法
NSStringFromSelector(@selector *( “setName:”));
理解一个对象被创建需要的三个步骤
开辟内存空间,初始化参数,返回内存地址值
layoutSubView何时调用
1)初始化方法时不会调用
2)滚动UIScrollview触发
3)旋转屏幕时触发
4)改变View的值时候触发,前提是frame改变了
5)改变UIView的大小时触发
理解OC是动态运行时语言
OC将数据,对象类型的确定从编译推迟到运行时。面向对象语言的多态性
1)运行时机制是我们知道运行的时候才确定一个对象的类型,以及调用该类别对象的指定方法。
2)多态,不同的对象以自己的方式来响应相同的东西,子类的指针可以赋值给父类
Http的状态码
1)302是请求重定向。
2)500及以上是服务器错误,如503表示服务器找不到、3840表示服务器返回无效JSON。
3)400及以上是请求链接错误或者找不到服务器,如常见的404。
4)200及以上是正确,如常见的是200表示请求正常。
区分类别与扩展
1)category 为已知的类增加新的方法,类别中扩展的方法会被子类继承
2)增加原有类的方法,而且是可以增加多个类别将大的功能划分为小功能
3)类目中的方法会比原有类中的方法具有更高优先级。所以不能和原有类方法重名否则覆盖
4)扩展:即延展,一般是在一个类的实现文件中。给当前类添加私有变量和私有方法。添加的方法是必须实现的。
区分#include、#import和@class
1)#include,导入C/C++文件,include相当于拷贝文件中的声明内容,多次使用就会报重复定义的错误。
2)#import,不会产生重复定义的错误,因为它会做一次判断,如果已经导入就不再导入了
3)@class仅仅是类的声明,告诉编译器有这么个类,具体这个类怎么定义一无所知,在编译的时候,速度更快,解决引用循环依赖死锁的问题(类的扩展,代理设计模式)
区分TCP和UDP
1)TCP:面向连接、传输可靠(保证数据正确性,保证数据顺序传输)、用于传输大量数据(流模式)、速度慢,建立连接需要开销较多。
2)UDP:面向非连接、传输不可靠、用于传输少量数据(数据包模式)、速度快,传输的是报文。
区分HTTP与Socket
1)HTTP请求:客户端主动发起请求,服务器才能给予响应,一次请求完毕后则断开连接,节省资源。
2)Socket:客户端与服务器端直接使用socket套接字连接,双方保持连接通道,都可以主动发送数据,适合游戏或股票等这种即时性很强的要求。主要使用的类是CFSockdetRef。
区分KVC和KVO
1)KVC:值编码,一种使用字符串标识属性,间接访问对象属性的方法。而不是调用存取方法。
2)KVO:观察者模式。通过监听对象的属性来更新UI或者状态。
区分define定义的宏和const定义的常量
1)define定义宏的指令,程序在预处理阶段将用#define所定义的内容只是进行了替换。程序运行时,常量表中并没有用#define所定义的宏,系统并不为它分配内存,不会检查类型。
2)const定义的常量,在程序运行时是存放在常量表中,系统会为它分配内存,而且在编译时会进行类型检查。
区分id与instancetype
1)id:万能指针,指向任意类型
2)instancetype:只能作为方法的范围类型,并且返回的类型是当前定义类的类型。
区分通知和代理
1)同:都用于对象之间的通信
2)异:代理是一对一通信。通知可以一对一,也可以一对多
区分methord和selector
selector只是一个方法名,而method包含了方法名和方法实现。
区分isKindOfClass 与isMemberOfClass
1)isKindOfClass:确定一个对象是否是一个类的成员,或者是派生自该类的成员.
2)isMemberOfClass:确定一个对象是否是当前类的成员.
3)注:isMemberOfClass不能检测任何的类都是基于NSObject类这一事实,而isKindOfClass可以。
区别面向过程和面向对象
1)面向过程:以事件为编程中心,各功能的实现是按照事件的先后顺序或者因果关系来展开的编程的一种思想
2)面向对象:以对象为编程的中心,以事件为驱动,各功能是模块化的,彼此之间独立互不影响的一种编程思想。
内存优化的方案
1)首选使用ARC环境开发,但是也要注意防止循环引用的产生,避免内存泄漏
2)懒加载,延迟创建对象,需要的时候才创建节省内存消耗
3)复用,单元格的服用,避免过多的创建对象
4)选择正确的是数据结构,不必要的时候不使用可变容器
5)单例模式
6)及时删除缓存信息