如何避免值未变更时重复写入SwiftUI Preference?
解决方案:在PreferenceKey中添加值相等判断
你可以直接修改ViewSizePreferenceKey的reduce方法,仅当新尺寸与当前保存的值不同时,才更新Preference的值。这样SwiftUI就不会因为重复的相同值触发不必要的onPreferenceChange回调,从根源上解决重复写入和警告问题。
修改后的PreferenceKey代码:
struct ViewSizePreferenceKey: PreferenceKey { static var defaultValue: CGSize = .zero static func reduce(value: inout CGSize, nextValue: () -> CGSize) { let newValue = nextValue() // 仅当新尺寸与当前值不同时更新 if newValue != value { value = newValue } } }
补充说明:
- 浮点精度问题处理:如果你的视图尺寸涉及浮点计算,可能会出现精度误差,此时可以用
CGSize的equalTo(_:)方法做精确匹配,或者自定义近似相等判断:
// 扩展CGSize添加近似相等方法 extension CGSize { func isApproximatelyEqual(to other: CGSize, tolerance: CGFloat = 0.001) -> Bool { abs(width - other.width) < tolerance && abs(height - other.height) < tolerance } } // 修改reduce中的判断逻辑 static func reduce(value: inout CGSize, nextValue: () -> CGSize) { let newValue = nextValue() if !newValue.isApproximatelyEqual(to: value) { value = newValue } }
- 原理说明:SwiftUI的Preference更新机制中,只有当
reduce方法最终修改了value的值时,才会触发onPreferenceChange回调。通过在reduce中添加相等判断,我们拦截了重复的相同值更新,避免了无意义的回调和Xcode警告。
你的视图扩展代码不需要做任何修改,就能直接受益于这个优化。
内容的提问来源于stack exchange,提问作者Duck
相关产品推荐
相关产品推荐

