从SwiftUI,我试图使用按钮在UIViewControllerRepresentable中实现文本更改,但可能缺少有关绑定的关键概念。
在SwiftUI中:
struct MainView: View {
@State private var textHere = "Set up text"
var body: some View {
return VStack{
DisplayView(text: $textHere)
Button(action:{
self.textHere = "Button update text"
}) {
HStack {
Text("Change the text by clicking")
.background(Color.white)
}
}
.background(Color.blue)
}
}
}
然后我有一个UIViewControllerRepresentable:
struct DisplayView: UIViewControllerRepresentable {
@Binding var text: String
func makeUIViewController(context: UIViewControllerRepresentableContext< DisplayView >) -> UIViewController {
let controller = DisplayViewController()
controller.text = text
return controller
}
func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext< DisplayView >) {
let controller = DisplayViewController()
controller.text = text
controller.updateText()
}
}
我的ViewController:
class CameraViewController : UIViewController {
var text = "Hello"
var textViewTest = UILabel()
func updateText(){
print("update text " + text)
self.textViewTest = UILabel(frame: CGRect(x: 40.0, y: 120.0, width: 250.0, height: 100.0))
...
self.textViewTest.text = text
}
override func viewDidLoad() {
super.viewDidLoad()
self.textViewTest = UILabel(frame: CGRect(x: 40.0, y: 120.0, width: 250.0, height: 100.0))
...
self.textViewTest.text = text
view.addSubview(self.textViewTest)
}
}
我已经尝试了updateText()函数的一些变体。
通过单击按钮传递数据:
但是值传递不会在标签上显示为更改。
似乎是在ViewController中进行了更新,但SwiftUI视图没有更新?
编辑:
This article向我指出了“包装” UIRepresentable的方向。这是新版本:
struct DisplayView: UIViewControllerRepresentable {
typealias UIViewControllerType = CameraViewController
var text: String?
func makeUIViewController(context: UIViewControllerRepresentableContext< DisplayView >) -> CameraViewController {
print("view called")
return CameraViewController()
}
func updateUIViewController(_ cameraViewController: CameraViewController, context: UIViewControllerRepresentableContext< DisplayView >) {
print("View updated")
cameraViewController.text = text
}
}
ViewController已更新:
final class CameraViewController : UIViewController {
var text: String? {
didSet {
updateController()
}
}
private var ccmeraViewController: CameraViewController?
func updateController(){
let textViewTest = UILabel(frame: CGRect(x: 40.0, y: 120.0, width: 250.0, height: 100.0))
guard let text = text else { return }
textViewTest.center = self.view.center
textViewTest.textAlignment = NSTextAlignment.justified
textViewTest.textColor = UIColor.blue
textViewTest.backgroundColor = UIColor.lightGray
textViewTest.text = text
view.addSubview(textViewTest)
}
override func viewDidLoad() {
super.viewDidLoad()
//updateController()
}
太好了!现在,我们可以正确地从SwiftUI将String值传递给ViewController并更新标签。
但是,当您第一次打开页面时,都会同时调用makeUIViewController和updateUIViewController,因此标签的两个实例相互重叠。
所以最后一步是弄清楚如何只显示一次UILabel。
更新3和部分解决方案
包含解决方案can be found here的最小存储库。
答案是正确的,您需要添加@Binding。但是,有趣的是,将字符串绑定到显示标签的ViewController会导致在视图中出现标签的两个实例。
通过将UILabel从SwiftUI绑定到UIViewControllerRepresentable,可以解决此问题,但是当String值更新时,标签会更改位置。
我不清楚:a)为什么UIViewControllerRepresentable接收到两个更新视图的请求,或者b)为什么UILabel更改位置。
同样,从SwiftUI绑定UILabel也没有多大意义。这本来是对嵌入ViewController并使用它们显示标签的测试,但这并不是您真正想要做的,但是为什么发生这些问题却没有多大意义。
答案 0 :(得分:1)
您可能需要像这样绑定text
:
struct DisplayView: UIViewControllerRepresentable {
typealias UIViewControllerType = CameraViewController
@Binding var text: String
....