OC语言

2019-08-14  本文已影响0人  BigBossZhu

1. 分类?做了哪些事情?
1. 声明私有方法
2. 分解类文件(体积庞大,按功能分类)
3. 将Framework的私有方法公开化.未公开的方法可以重写调用
特点:
运行时决议.在运行时通过runtime动态添加
可以为系统类添加分类.

分类中可以添加哪些内容?
1. 可以添加实例方法
2. 可以添加类方法
3. 协议
4. 属性(只申明set,get方法并没有添加实例变量)

分类结构:

    name:分类名称
    class:表示分类宿主类
    method_list_t *instanceMethods:实例方法列表
    method_list_t *classMethods:类方法列表
    method_list_t *protocols:协议列表
    method_list_t *instanceProperties:实例属性列表

源码分析:
1. 最先访问最后编译的分类.最后编译的分类中的方法会覆盖之前的方法.生效.
2. 分类方法会'覆盖'宿主类方法,分类方法位于打头的位置会被优先实现.
3. 名字相同的分类会引起编译报错.
关联对象:怎样为分类添加成员变量.
能为分类添加成员变量,但是是通过关联对象的技术.
id objc_getAssociatedObject()
void objc_setAssociatedObject()
void objc_removeAssociatedObject()

关联对象的本质:
关联对象由AssociationsManager管理并在AssociationsHashMap中存储.所有对象的关联内容都在同一个全局容器中.

2. 扩展:
1. 一般用扩展做什么?
1. 声明私有属性
2. 声明私有方法
3. 申明私有成员变量(开发中一般直接放在.m文件中)
特点:
编译时决议
只以声明的形式存在,多数情况下寄生在宿主类.m文件中
不能为系统类添加扩展

3. 代理:
准确的说是一种设计模式.(代理模式)
@protocol
传递方式1对1.通知时1对多的.
单层传递

代理的工作流程:
协议.代理方,委托方.
可以定义属性和方法
代理方必须要都实现协议的方法吗?
不一定需要.声明的方法require必须实现.option可以实现可以不实现.
注意: 1. 一般申明引用代理方为weak被委托方持有,从而规避循环引用

4. 通知:
1对多(一个通知多个接收,但是注意delloc中释放通知)
使用观察者模式设计模式实现
跨层传递
具体实现原理:
notification_map为一个数组元素为字典,key:name对应value:数组内含多个观察者.

5. KVO:
什么是KVO:Key-value observing

  1. KVO是观察者模式的一种实现.
  2. 系统采用isa混写(isa-swizzling)来实现KVO.
    isa混写技术是什么?怎样实现的?
    当我们调用A类的addObserverForKeyPath方法的之后系统会在运行时动态创建一个当前类的子类(Notification_A),这个子类会重写监听属性的set方法来通知所有观察者,这个时候会将原来类的isa指针指向新创建的这个子类,把isa的指向进行修改实际上就是isa混写技术.
    通过代码打印class在addObserverForKeyPath之后类名改变发现确实是这样的
    重写setter方法具体实现是怎么样的呢?
    首先调用willChangeValueForKey.再调用父类的setValue方法(作用:不会对父类setter方法产生干扰),再调用didChangeValueForKey方法(此方法会触发kvo回调).
    问题:通过KVC设置和成员变量赋值能否生效?
    注意:KVC生效,成员变量不生效.为啥?涉及到KVC的实现和原理(KVC会调用A类的setter方法).
    问题:手动KVO是怎么样的?
    在复制前后添加willChangeValueForKey,和didChangeValueForKey方法.就能模拟系统KVO实现.

6. KVC:
什么是KVC:Key-value coding键值编码技术.
KVC编码技术会破坏面向对象的思想,尽量少使用这种编码技术.
valueForKey系统实现流程:
首先查找key对应的实例变量是否有getter方法,没有,会查找是否存在此实例变量,没有继续调用valueForUndefinedKey.抛出NSUndefineKeyException异常结束调用.(注意此处使用的是模糊查找类似key也能够查找到).
setValueForKey类似.只是是set方法.

7. 属性关键字:

  1. 读写权限(readonly,readwrite默认)
  2. 原子性(atomic默认,nonatimic).赋值和获取是线程安全的.
  3. retain/strong,assign/unsafe_unretained,weak,copy
    assgin和weak关键字的区别有哪些呢?
    assgin常用修饰的是基本数据类型但也可修饰对象,不改变引用计数,再被释放会仍然指向原对象.
    weak修饰的是对象,不改变引用计数.所指对象再被释放之后会自动置为nil.

** copy关键字. **
浅拷贝:内存地址复制.增加被拷贝指针的引用计数.
深拷贝:产生新的内存分配.新的指针指向新的内存空间,只是内容相同.
如何区分深拷贝和浅拷贝?
深拷贝会产生新的内存空间.浅拷贝影响了引用计数.(注意mutableCopy拷贝一定是可变对象,只有不可变对象copy才是浅拷贝其他都是深拷贝).

copy修饰可变数组会产生什么问题.
会导致程序异常,如果指针指向可变对象copy会变成不可变,如果指向不可变对象会变成不可变.但是会调用可变数据内部方法,就会产生异常.

上一篇下一篇

猜你喜欢

热点阅读