Pressing the "FIRST" or "SECOND" Text views should change the State selection
and update selectedView
accordingly. While the debugger shows that pressing "FIRST" or "SECOND" causes body
to be re-evaluated and correctly assigns selectedView
, the screen never updates to show the correct view. Instead, the screen only shows the view that corresponds to selection
's initialized state and remains stuck on that view.
import UIKit
import SwiftUI
struct TestView: View {
@State private var selection: Int = 1
var body: some View {
let firstView = TestRepresentable(string: "First View")
let secondView = TestRepresentable(string: "Second View")
let selectedView = selection == 1 ? firstView : secondView
let finalView = VStack {
HStack {
Text("FIRST").onTapGesture { self.selection = 1 }.padding()
Text("SECOND").onTapGesture { self.selection = 2 }.padding()
}
selectedView
}
return finalView
}
}
struct TestRepresentable: UIViewControllerRepresentable {
let string: String
func makeUIViewController(context: Context) -> TestVC {
return TestVC().create(string)
}
func updateUIViewController(_ uiViewController: TestVC, context: Context) {
//...
}
func makeCoordinator() -> Coordinator {
Coordinator(testRepresentable: self)
}
class Coordinator: NSObject {
var testRepresentable: TestRepresentable
init(testRepresentable: TestRepresentable) {
self.testRepresentable = testRepresentable
}
}
}
class TestVC: UIViewController {
private let label = UILabel()
override func loadView() {
super.loadView()
view.addSubview(label)
label.translatesAutoresizingMaskIntoConstraints = false
label.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
label.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
label.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
label.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
}
func create(_ string: String) -> TestVC {
label.text = string
return self
}
}
When I swap TestRepresentable(string: "First View")
with Text("First View")
(and do the same for "Second View"), the screen updates correctly. Something about my UIViewController or UIViewControllerRepresentable implementations prevent changes in my SwiftUI view from rendering on the screen. Why don't changes to the State variable selection
render the correct selectedView
?
It is just not a SwiftUI coding (so body could not correctly track state changes), here is a fixed part of code (tested with Xcode 13 / iOS 15)
var body: some View {
VStack {
HStack {
Text("FIRST").onTapGesture { self.selection = 1 }.padding()
Text("SECOND").onTapGesture { self.selection = 2 }.padding()
}
if selection == 1 {
TestRepresentable(string: "First View")
} else {
TestRepresentable(string: "Second View")
}
}
}