SwiftUI中onPreferenceChange未触发问题求助
问题原因与修复方案
你的代码核心问题是PreferenceKey的传递路径错误:Preference是从子视图向上传递到祖先视图的,只有祖先视图上的onPreferenceChange才能接收到子视图发送的Preference值。但你把监听Preference的titleByKey修饰符加在了Text组件上,而ChildView和Text是同级视图,ChildView的Preference无法传递到同级的Text修饰符中,导致onPreferenceChange完全不会触发。
修复步骤
1. 调整修饰符的位置
将titleByKey修饰符从Text移到包含Text和ChildView的VStack上,让监听Preference的视图成为ChildView的直接祖先:
struct MainView: View { @State var title: String = "DEF" var body: some View { VStack { Text(title) .padding() .font(.system(size: 20)) .foregroundStyle(Color.black) ChildView() } .titleByKey(title: $title) // 移到VStack上 } }
2. 可选优化:完善PreferenceKey的reduce逻辑
原reduce方法会直接覆盖现有值,如果有多个子视图发送Preference,只会保留最后一个的值。可以添加非空判断,避免空字符串覆盖原有标题:
struct TitleChangePreferenceKey: PreferenceKey { static var defaultValue: String = "" static func reduce(value: inout String, nextValue: () -> String) { let newValue = nextValue() // 仅当新值非空时更新 if !newValue.isEmpty { value = newValue } } }
修复后效果
修改后,当你在ChildView的输入框中输入内容时,updateTitleByKey会发送新的Preference值,向上传递到VStack的titleByKey修饰符中,触发onPreferenceChange更新title状态,最终Text会同步显示输入的内容。
内容的提问来源于stack exchange,提问作者Abhishek Thapliyal
相关产品推荐
相关产品推荐

