Situation
During migration of some UIKit view classes to SwiftUI, I have faced next case:
I have a simple view class, responsible for data fetching and displaying. Its structure is pretty simple and can be recreated in swiftui in next way:
struct NewView: View {
@State private var isLoader: Bool = false
var body: some View {
VStack {
Text("Data here")
if isLoader {
Text("Loading")
}
}
}
func startNetworkRequest() {
isLoader = true
// Data fetching request here
isLoader = false
}
}
In order to use new view in UIKit env, I've made a host controller:
class HostVC: UIHostingController<NewView> {
convenience
init() {
self.init(rootView: NewView())
}
func startNetworkRequest() {
rootView.startNetworkRequest()
}
}
The problem:
If we call startNetworkRequest on hostVC instance, isLoader value don't change
print("isLoading value before update: \(isLoading)")
isLoading = true
print("isLoading value before request: \(isLoading)")
It gives me:
isLoading value before update: false
isLoading value before update: false
Question:
Is there any way to implement expected behaviour:
- To have UI written in SwiftUI
- It should be available in UIKit classes (via UIHostController, I assume)
- To be able to trigger some view events via host controller methods
Kind of solution:
I moved startNetworkRequest call inside the view (in onAppear) and it worked as expected. It doesn't solve my #3 expected behaviour point, but works for current task so I've to go with it for now
My assumption:
When we access view via hostVC, we are working with its immutable instance (since it's struct) and any property changes (although they are correct from syntax perspective) aren't applied.
When we work "from inside", we work with view container, which can modify its content and replace old struct instance with new one, modified.
It seems my assumption was kind of correct and we can't edit view state from from outside
As a potential solution, we can store needed property as reference value or in another place:
Usage:
if isLoading.value { ...,isLoading.value = trueetc