Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/42.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如果KVO观察到的值在短时间内更改了两次,那么在observeValueForKeyPath()中会发生什么情况?_Ios_Iphone_Multithreading_Swift_Key Value Observing - Fatal编程技术网

Ios 如果KVO观察到的值在短时间内更改了两次,那么在observeValueForKeyPath()中会发生什么情况?

Ios 如果KVO观察到的值在短时间内更改了两次,那么在observeValueForKeyPath()中会发生什么情况?,ios,iphone,multithreading,swift,key-value-observing,Ios,Iphone,Multithreading,Swift,Key Value Observing,据我所知,由于我没有为我的KVO(Swift中的observeValueForKeyPath)使用单独的线程,当我观察到某个值发生更改时,将使用同一个线程调用observeValueForKeyPath()。我不确定的是,如果我在ValeActudioFixPATH()的中间,那么值再次改变,会发生什么?我当前的执行是否会被中断,并再次从observeValueForKeyPath()的开头开始?在这种情况下,在后一个observeValueForKeyPath()完成后,是否恢复到中断的前一个

据我所知,由于我没有为我的KVO(Swift中的observeValueForKeyPath)使用单独的线程,当我观察到某个值发生更改时,将使用同一个线程调用observeValueForKeyPath()。我不确定的是,如果我在ValeActudioFixPATH()的中间,那么值再次改变,会发生什么?我当前的执行是否会被中断,并再次从observeValueForKeyPath()的开头开始?在这种情况下,在后一个observeValueForKeyPath()完成后,是否恢复到中断的前一个observeValueForKeyPath()?在这种情况下,如果我在observeValueForKeyPath()中操作数据,我假设它会导致竞争条件。
谢谢。

KVO真的很酷。实际发生的情况(如所发现的)是,运行时将子类化您的observed对象,并覆盖正在观察的属性的setter。被重写的setter具有额外的指令,这些指令最终将显式调用
-observeValueForKey
,用于观察对象

因此,如果在
-observeValueForKey
中从更改指定键路径处的值,那么会发生什么情况,您只会得到将
-observeValueForKey
消息发送到观察到的(相同)对象。因此,正如您所说,您当前的执行将被中断,一些与KVO相关的堆栈帧将被放置在您的调用堆栈上,如果所有问题都得到正确解决,您将像正常一样继续执行

当然,令人厌倦的是,如果在对象的
-observeValueForKey
内部,您总是向同一对象发出通知。你将陷入无限循环,你的应用程序将崩溃


我不会把你所描述的称之为竞争条件,因为在任何时候都不会有两个对象试图同时读/写一个对象。你只需要厌倦你阅读和写作的顺序,因为这可能不是你所期望的

@A是的,你是对的,这不是比赛条件。只是,假设在observeValueForKey中,我有一个double数组要处理,虽然我还没有处理完所有的double数组,但可能会发生另一个observeValueForKey数组。这将导致最后的值不正确。这个问题会发生,对吗?对。您只需确保在
-observeValueForKey
中没有启动KVO通知,除非您明确希望这样做。解决这个问题的方法是设置backing
ivar
(例如,
\u myProperty
),而不是调用合成setter(例如,
self.myProperty
)。通过直接设置
ivar
,您可以绕过运行时生成的覆盖setter来触发KVO通知