@Binding 值更改时更新 UIView(在 UIViewRepresentable 内)
Update UIView (inside UIViewRepresentable) when @Binding value changes
我尝试在绑定值发生变化时更新 UIView(在 UIViewRepresentable 中),但我不知道如何捕捉绑定值的变化来更新 UIView?我使用了接收函数,但显示一条警告消息(接收未使用的调用结果)
示例代码:
struct CustomPickerView: UIViewRepresentable {
let data: [String]
@Binding var selectedValue: String
//makeCoordinator()
func makeCoordinator() -> CustomPickerView.Coordinator {
return CustomPickerView.Coordinator(self)
}
//makeUIView(context:)
func makeUIView(context: UIViewRepresentableContext<CustomPickerView>) -> UIPickerView {
let picker = UIPickerView(frame: .zero)
// allows rows to be compressed in swiftUI
picker.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
picker.setContentCompressionResistancePriority(.defaultLow, for: .vertical)
// allows rows to be expanded
picker.setContentHuggingPriority(.defaultLow, for: .horizontal)
picker.dataSource = context.coordinator
picker.delegate = context.coordinator
picker.selectRow(data.firstIndex(of: selectedValue) ?? 0, inComponent: 0, animated: false)
return picker
}
//updateUIView(_:context:)
func updateUIView(_ view: UIPickerView, context: UIViewRepresentableContext<CustomPickerView>) {
onReceive(selectedValue.publisher) { newValue in
// I try to update the picker view selected row when binding value changes...
view.selectRow(data.firstIndex(of: newValue.debugDescription) ?? 0, inComponent: 0, animated: true)
}
}
// The rest of code ...
}
不需要使用onReceive
和watch publisher -- updateUIView
会在selectedValue
变化时被调用,直接使用即可:
struct ContentView: View {
@State private var selected = "3"
var body: some View {
CustomPickerView(data: ["1","2","3"], selectedValue: $selected)
Button("Choose 1") {
selected = "1"
}
}
}
struct CustomPickerView: UIViewRepresentable {
let data: [String]
@Binding var selectedValue: String
//makeCoordinator()
func makeCoordinator() -> CustomPickerView.Coordinator {
return CustomPickerView.Coordinator(self)
}
//makeUIView(context:)
func makeUIView(context: UIViewRepresentableContext<CustomPickerView>) -> UIPickerView {
let picker = UIPickerView(frame: .zero)
// allows rows to be compressed in swiftUI
picker.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
picker.setContentCompressionResistancePriority(.defaultLow, for: .vertical)
// allows rows to be expanded
picker.setContentHuggingPriority(.defaultLow, for: .horizontal)
picker.dataSource = context.coordinator
picker.delegate = context.coordinator
picker.selectRow(data.firstIndex(of: selectedValue) ?? 0, inComponent: 0, animated: false)
return picker
}
func updateUIView(_ view: UIPickerView, context: UIViewRepresentableContext<CustomPickerView>) {
view.selectRow(data.firstIndex(of: selectedValue) ?? 0, inComponent: 0, animated: true)
}
class Coordinator : NSObject, UIPickerViewDataSource, UIPickerViewDelegate {
func numberOfComponents(in pickerView: UIPickerView) -> Int {
1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
parent.data.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String?
{
parent.data[row]
}
var parent: CustomPickerView
init(_ input : CustomPickerView) {
self.parent = input
}
}
}
我尝试在绑定值发生变化时更新 UIView(在 UIViewRepresentable 中),但我不知道如何捕捉绑定值的变化来更新 UIView?我使用了接收函数,但显示一条警告消息(接收未使用的调用结果)
示例代码:
struct CustomPickerView: UIViewRepresentable {
let data: [String]
@Binding var selectedValue: String
//makeCoordinator()
func makeCoordinator() -> CustomPickerView.Coordinator {
return CustomPickerView.Coordinator(self)
}
//makeUIView(context:)
func makeUIView(context: UIViewRepresentableContext<CustomPickerView>) -> UIPickerView {
let picker = UIPickerView(frame: .zero)
// allows rows to be compressed in swiftUI
picker.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
picker.setContentCompressionResistancePriority(.defaultLow, for: .vertical)
// allows rows to be expanded
picker.setContentHuggingPriority(.defaultLow, for: .horizontal)
picker.dataSource = context.coordinator
picker.delegate = context.coordinator
picker.selectRow(data.firstIndex(of: selectedValue) ?? 0, inComponent: 0, animated: false)
return picker
}
//updateUIView(_:context:)
func updateUIView(_ view: UIPickerView, context: UIViewRepresentableContext<CustomPickerView>) {
onReceive(selectedValue.publisher) { newValue in
// I try to update the picker view selected row when binding value changes...
view.selectRow(data.firstIndex(of: newValue.debugDescription) ?? 0, inComponent: 0, animated: true)
}
}
// The rest of code ...
}
不需要使用onReceive
和watch publisher -- updateUIView
会在selectedValue
变化时被调用,直接使用即可:
struct ContentView: View {
@State private var selected = "3"
var body: some View {
CustomPickerView(data: ["1","2","3"], selectedValue: $selected)
Button("Choose 1") {
selected = "1"
}
}
}
struct CustomPickerView: UIViewRepresentable {
let data: [String]
@Binding var selectedValue: String
//makeCoordinator()
func makeCoordinator() -> CustomPickerView.Coordinator {
return CustomPickerView.Coordinator(self)
}
//makeUIView(context:)
func makeUIView(context: UIViewRepresentableContext<CustomPickerView>) -> UIPickerView {
let picker = UIPickerView(frame: .zero)
// allows rows to be compressed in swiftUI
picker.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
picker.setContentCompressionResistancePriority(.defaultLow, for: .vertical)
// allows rows to be expanded
picker.setContentHuggingPriority(.defaultLow, for: .horizontal)
picker.dataSource = context.coordinator
picker.delegate = context.coordinator
picker.selectRow(data.firstIndex(of: selectedValue) ?? 0, inComponent: 0, animated: false)
return picker
}
func updateUIView(_ view: UIPickerView, context: UIViewRepresentableContext<CustomPickerView>) {
view.selectRow(data.firstIndex(of: selectedValue) ?? 0, inComponent: 0, animated: true)
}
class Coordinator : NSObject, UIPickerViewDataSource, UIPickerViewDelegate {
func numberOfComponents(in pickerView: UIPickerView) -> Int {
1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
parent.data.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String?
{
parent.data[row]
}
var parent: CustomPickerView
init(_ input : CustomPickerView) {
self.parent = input
}
}
}