SwiftUI | 警告:绑定首选项 _ 尝试每帧更新多次。可能的原因?

Mof*_*waw 8 ios swiftui

自从我使用首选项 ( PreferenceKey,..)以来,我在控制台中收到此消息:

Bound preference _ tried to update multiple times per frame.

经过无数次的研究,我还没有找到任何方法可以让它静音。所以...既然还没有特别针对此警告的问题,您认为可能的原因是什么?

如果没有,可以忽略此警告还是我必须修复它?

非常感谢!

(我试图找到一个例子,但不知何故我没有得到任何简单的警告......)

kul*_*ich 19

我认为苹果工程师的这个回答描述了一般性问题:

\n
\n

听起来你的更新有一个周期。例如,写入首选项的 GeometryReader 会导致包含视图调整大小,从而导致 GeometryReader 再次写入首选项。避免创建此类循环非常重要。通常,这可以通过将 GeometryReader 在视图层次结构中移动到更高的位置来完成,这样它的大小就不会改变,并且可以将大小传达给其子视图,而不是使用首选项。我\xe2\x80\x99恐怕我无法\xe2\x80\x99在没有看到你的代码的情况下提供\n更具体的指导,但是\n希望这可以帮助你找到问题!

\n
\n

https://www.bigmountainstudio.com/community/public/posts/65727-wwdc-2021-questions-answers-from-slack-the-unofficial-archive

\n

至少它激励我解决了我的案例中的相关错误并使警告消失(几乎:))。

\n


mbx*_*Dev 6

SwiftUI 更改处理程序,例如onPreferenceChange在任意线程上调用。因此,如果这些更改影响您的视图,您应该重新调度以确保在主线程上进行这些更新:

.onPreferenceChange(MyPreferenceKey.self) { newValue in
    DispatchQueue.main.async {
        widget.value = newValue
    }
}
Run Code Online (Sandbox Code Playgroud)

  • “在任意线程上调用 SwiftUI 更改处理程序(例如 onPreferenceChange)”为 false。在处理程序中运行“Thread.isMainThread”将给出“true”。这里还有其他事情发生 (9认同)
  • 唔。这并没有为我解决问题。就我而言,我在许多不同的视图中使用相同的 PreferenceKey。这是一个有效的方法吗?具体来说,我正在确定某些视图的宽度,以便调整姐妹视图的大小。 (3认同)
  • 这一点非常重要,也有些令人惊讶,但仔细想想,这是有道理的。不过,应该更好地记录它。另外,在多个子视图上使用相同的首选项键似乎确实会引发这种行为。不确定正确的方法是什么。 (3认同)
  • onPreferenceChange 在 main 上调用 (2认同)
  • `DispatchQueue.main.async` 不仅仅是在主线程上运行一些代码。它还将其排队以在主线程上执行,这意味着其他排队的代码首先运行,或者换句话说,**传递的块中的代码被推迟到稍后**。根据您的具体用例,这种延迟可能会消除警告,因为跨越了帧边界。(并不是说这解决了问题,因为你实际上减慢了渲染速度,但它可以消除错误。)实际的解决方案是修复重绘循环,这是 @kulich 的答案引用了 Apple 工程师的答案。 (2认同)