mirror of
https://github.com/NohamR/knowledge-kit.git
synced 2026-05-25 04:17:17 +00:00
docs: image url
This commit is contained in:
@@ -24,7 +24,7 @@
|
||||
|
||||
在需要触发 KVO 的地方,先调用 `willChangeValueForKey`,然后更改被观察对象的属性值,最后调用 `didChangeValueForKey` 方法。
|
||||
|
||||
<img src="./../assets/KVOInvokeWhenChangeIvarDirectlyMustCallWillChangeAndDidChange.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/KVOInvokeWhenChangeIvarDirectlyMustCallWillChangeAndDidChange.png" style="zoom:25%">
|
||||
|
||||
|
||||
|
||||
@@ -214,7 +214,7 @@ Demo: 实时数据流处理
|
||||
|
||||
代码如下
|
||||
|
||||
<img src="./../assets/KVOObservePropertyIsObject.png" style="zoom:40%" />
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/KVOObservePropertyIsObject.png" style="zoom:40%" />
|
||||
|
||||
看上去很麻烦,有没有优雅点的方案?
|
||||
|
||||
@@ -224,7 +224,7 @@ Demo: 实时数据流处理
|
||||
|
||||
实现如下:
|
||||
|
||||
<img src="./../assets/KVOObservePropertyIsObjectUseAPI.png" style="zoom:40%" />
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/KVOObservePropertyIsObjectUseAPI.png" style="zoom:40%" />
|
||||
|
||||
注意:在对 Person 对象的 `dog` 属性进行监听后,Person 内部需要实现 `+`keyPathsForValuesAffectingValueForKey 方法,判断 key 为 `@"dog"` 后,想监听 dog 的哪个属性变化就通知 Person 对象的观察者收到响应的话就写上去。但注意绿色框里面,set 添加的内容,必须换个名字,比如 `@"_dog.name"`,不能是 `@"dog.name"`。这会导致循环依赖或逻辑矛盾
|
||||
|
||||
@@ -326,7 +326,7 @@ self.p1.dog.name = @"Lucy";
|
||||
|
||||
可以在下面的 Demo1 中可以看到 KVO 无法直接对数组进行 KVO 监听。但系统为了方便,也提供了容器类的接口,比如针对 `NSMutableArray` 系统就提供了 `mutableArrayValueForKey` 接口。
|
||||
|
||||
<img src="./../assets/KVOObserveNSMutableArrayUseAPI.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/KVOObserveNSMutableArrayUseAPI.png" style="zoom:25%">
|
||||
|
||||
那么虽然功能实现了,我们可以想想,这个接口背后做了哪些事?
|
||||
|
||||
@@ -434,7 +434,7 @@ FBKVO 工作原理:
|
||||
|
||||
### Demo1
|
||||
|
||||
<img src="./../assets/KVOInstanceVariableCannotObserve.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/KVOInstanceVariableCannotObserve.png" style="zoom:25%">
|
||||
|
||||
可以发现对成员变量添加观察者的时候,成员变量的值变化了,KVO 也是监听不到的
|
||||
|
||||
@@ -442,13 +442,13 @@ FBKVO 工作原理:
|
||||
|
||||
### Demo2
|
||||
|
||||
<img src="./../assets/KVOCannotObserveNSMutableArray.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/KVOCannotObserveNSMutableArray.png" style="zoom:25%">
|
||||
|
||||
可以看到对 NSMutableArray 类型的属性添加了 KVO。然后点击屏幕,NSMutableArray 里添加了元素,但是观察方法没有触发。
|
||||
|
||||
对实验进行改进下
|
||||
|
||||
<img src="./../assets/KVOObserveNSMutableArray.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/KVOObserveNSMutableArray.png" style="zoom:25%">
|
||||
|
||||
结论: **KVO 只可以对属性的 setter 方法起作用**。
|
||||
|
||||
@@ -458,7 +458,7 @@ FBKVO 工作原理:
|
||||
|
||||
创建 Person 类,点击事件里触发属性值的改变
|
||||
|
||||
<img src="./../assets/XCodoKVOIsaInspect.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/XCodoKVOIsaInspect.png" style="zoom:25%">
|
||||
|
||||
分析:
|
||||
|
||||
@@ -468,7 +468,7 @@ FBKVO 工作原理:
|
||||
|
||||
在内存中的结构如下图
|
||||
|
||||
<img src="./../assets/UnusedKVOIsaStructure.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/UnusedKVOIsaStructure.png" style="zoom:25%">
|
||||
|
||||
整个流程分析下:
|
||||
|
||||
@@ -478,11 +478,11 @@ FBKVO 工作原理:
|
||||
|
||||
当我们按照 KVO 后动态生成的类名去创建一个新的类的时候,Xcode 会报错:`[general] KVO failed to allocate class pair for name NSKVONotifying_Person, automatic key-value observing will not work for this class`。因为自己创建的类名和系统将要动态创建的类名冲突了,并且 KVO 监听失效
|
||||
|
||||
<img src="./../assets/SelfClassNameConflictsWithKVOClass.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/SelfClassNameConflictsWithKVOClass.png" style="zoom:25%">
|
||||
|
||||
### Demo4
|
||||
|
||||
<img src="./../assets/KVOMethodImplAddressAndIsaInspect.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/KVOMethodImplAddressAndIsaInspect.png" style="zoom:25%">
|
||||
|
||||
分析:
|
||||
|
||||
@@ -494,7 +494,7 @@ FBKVO 工作原理:
|
||||
|
||||
### Demo5
|
||||
|
||||
<img src="./../assets/KVOMethodImplAddressWithDouble.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/KVOMethodImplAddressWithDouble.png" style="zoom:25%">
|
||||
|
||||
可以看到我们将 KVO 的数据类型改为 double 后,原本的 setHeight 是 `_NSSetLongLongValueAndNotify`,现在是 `_NSSetDoubleValueAndNotify`
|
||||
|
||||
@@ -504,11 +504,11 @@ FBKVO 工作原理:
|
||||
|
||||
### NSSet**ValueAndNotify 的内部实现
|
||||
|
||||
<img src="./../assets/UsedKVOIsaStructure.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/UsedKVOIsaStructure.png" style="zoom:25%">
|
||||
|
||||
来对 Person 类增加一些打印方法
|
||||
|
||||
<img src="./../assets/KVOKeyMethodPrint.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/KVOKeyMethodPrint.png" style="zoom:25%">
|
||||
|
||||
|
||||
|
||||
@@ -577,7 +577,7 @@ FBKVO 工作原理:
|
||||
|
||||
### 重写 class 方法
|
||||
|
||||
<img src="./../assets/KVOOverrrideClassMethod.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/KVOOverrrideClassMethod.png" style="zoom:25%">
|
||||
|
||||
可以看到利用 runtime api,在添加 KVO 之后,类对象为 `NSKVONotifying_Person`
|
||||
|
||||
@@ -589,7 +589,7 @@ FBKVO 工作原理:
|
||||
|
||||
### KVO 类的所有方法
|
||||
|
||||
<img src="./../assets/PrintKVOClassAllMethodName.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/PrintKVOClassAllMethodName.png" style="zoom:25%">
|
||||
|
||||
|
||||
|
||||
@@ -663,7 +663,7 @@ Apple 文档告诉我们:被观察对象的 `isa指针` 会指向一个中间
|
||||
|
||||
- 键值观察通知依赖于 NSObject 的两个方法:`willChangeValueForKey:、didChangeValueForKey:` 。在一个被观察属性改变之前,调用 `willChangeValueForKey:` 记录旧的值。在属性值改变之后调用 `didChangeValueForKey:`,从而 `observeValueForKey:ofObject:change:context:` 也会被调用。
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
|
||||
@@ -809,7 +809,7 @@ KVO 的改装:
|
||||
|
||||
KVC 之后会触发 KVO 吗?
|
||||
|
||||
<img src="./../assets/KVCWillTriggerKVO.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/KVCWillTriggerKVO.png" style="zoom:25%">
|
||||
|
||||
发现 KVC 触发了 KVO。
|
||||
|
||||
@@ -817,7 +817,7 @@ KVC 之后会触发 KVO 吗?
|
||||
|
||||
整个流程如下
|
||||
|
||||
<img src="./../assets/KVC-process.png" style="zoom:45%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/KVC-process.png" style="zoom:45%">
|
||||
|
||||
`[self.person setValue:@10 forKey:@"age"]` 会先调用 `setKey:` 同名的方法,找不到则调用 `_setKey:` 的方法,如果还是找不到则调用 `+(BOOL)accessInstanceVariableDirectlt`,如果该方法返回 YES,则可以直接修改成员变量的值,会按照 `_key`、`_isKey`、`key`、`isKey` 的顺序寻找成员变量,如果找到则直接赋值,没找到则抛出异常 `NSUnknownKeyException`
|
||||
|
||||
@@ -874,7 +874,7 @@ KVC 之后会触发 KVO 吗?
|
||||
|
||||
|
||||
|
||||
<img src="./../assets/KVC-get-process.png" style="zoom:45%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/KVC-get-process.png" style="zoom:45%">
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user