iOS_2022_基础_1
1、load initiallize
调用方式和时刻
- 调用方式不同:
+load是根据函数地址直接调用;
initialize是通过objc_msgSend调用 - 调用时刻不同:
+load方法会在runtime加载类、分类时,在main() 函数之前调用(而且程序运行过程中只调用一次)。
+initialize是类第一次接收到消息的时候调用(即是类调用alloc时),每一个类只会initialize一次(下面提到子类没有实现+initialize,会调用父类的+initialize。这样父类的initialize方法可能会被调用多次)
所以一般会在 +load 方法中实现 Method Swizzle
initialize 方法应该限制做一些简单不复杂的类初始化的前期准备工作
2、category extension
iOS中分类(category)和类扩展(Extension)的区别
使用分类需要注意的几个点:
1.分类是用于给原有类添加方法的,因为分类的结构体指针中,没有实例变量的成员结构,所以原则上讲他只能添加方法,不能添加属性(成员变量),实际上他是可以通过其他方式来添加属性,比如关联对象(runtime)。但是使用runtime也只能实现setter和getter方法,而没有_成员变量,如果调用_成员变量,程序还是会报错。
2、如果要使用@property来给分类添加成员变量的话,需要手动写变量的setter和getter方法实现,否则添加的成员变量无法使用。因为在分类中不会生成setter和getter方法的实现,也不会生成以及实现私有的成员变量。
3、可以在分类中访问原有类.h中声明的属性。
4、如果分类中有和原有类同名的方法,会优先调用分类中的方法,就是说会忽略原有类的方法。所以同名方法调用的优先级为:分类>本类>父类。
5、如果多个分类中都有和原有类同名的方法,那么调用该用法的时候执行谁由编译器决定,编译器会执行最后一个参与编译的分类中的方法。
类扩展(Extention):
是Categary的一个特例。类扩展与分类相比只少了分类的名称,所以称之为“匿名分类”。(比如从xib文件中拖拽出来在.m文件中显示的属性和方法就是类扩展)
3、KVC
4、runtime
- 动态添加对象的成员变量和方法
- 动态的交换两个方法的实现
- 拦截替换方法
- 在方法上增加额外功能
- 实现NSCoding的自动归档和解档
- 实现字典模型的自动转换
- 对象 的类(Superclass)是 类(对象) ;
- 类(对象) 的类(Superclass)是 元类,和类同名;
- 元类 的类(Superclass)是 根元类 NSObject;
- 根元类 的类(Superclass)是 自己 ,还是NSObject;
- 对象的isa指针指向类(对象) ;
- 类对象的isa指针指向元类,和类同名;
- 元类的isa指针指向跟根元类 NSObject;
- 根元类 NSObject的isa指针指向自己。
我们创建的一个对象或实例其实就是一个struct objc_object结构体,而我们常用的id也就是这个结构体的指针。
这个结构体只有一个成员变量,这是一个Class类型的变量isa,也是一个结构体指针,isa指针就指向对象所属的类。
5、归档、解档
归档与解档是iOS中序列化与反序列化的方式,需要遵守NSCoding协议,实现 encodeWithCoder 和 initWithCoder 方法,实现方式有两种:第一种是分别为属性赋值;第二种是通过runtime机制,循环为属性赋值。
1、NSTimer
初始化
3个timerWith类方法:需要将将timer对象添加到当前runloop中
2个initWith实例方法:手动添加
3个scheduledTimer类方法:会自动将timer对象加到runloop中
开始
- (void)fire;
销毁与释放
invalidate
会停止重复的timer(不重复的执行一次后会自动invalidate),并将其从runloop中remove。
if ([_timer isValid]) { [_timer invalidate]; //对于不重复的timer可以不写,因为不重复的timer在执行完后就自动invalidate了 _timer = nil; }
2、CADisplayLink
3、GCD :dispatch_source_t
—–时间误差—–
- NSTimer回调的时间间隔可能会有存在误差。因为RunLoop每跑完⼀次圈再去检查当前累计时间是否已经达到定时器所设置的间隔时间,如果未达到,RunLoop将进⼊下⼀轮任务,待任务结束之后再去检查当前累计时间,⽽此时的累计时间可能已经超过了定时器的间隔时间,故可能会存在误差。
—–循环引用—–
- 使用block
- 使用NSProxy做转发。target —–> timer,timer —–> proxy,proxy – – -> target。
- 使用gcd timer。
对于CADisplayLink可以通过以下两种方式:NSProxy 、 使用category扩展block方法
7、NSProxy
8、消息转发机制
OC和Swift两种语言混合开发:
- 对于Swift语言调用OC的代码的处理方法是系统会为工程建立一个桥声明头文件:项目工程名-Bridging-Header.h,所有Swift需要调用的OC语言方法都需要在这个头文件中声明。
- 而对于OC语言调用Swift语言来说,则有一定的限制。因为Swift和OC的函数调用ABI规则不相同,OC语言只能创建Swift中从NSObject类中派生类对象,而方法调用则只能调用原NSObject类以及派生类中的所有方法以及被声明为@objc关键字的Swift对象方法。如果需要在OC语言中调用Swift语言定义的类和方法,则需要在OC语言文件中添加:#import “项目名-Swift.h”。