So basically I'm wrapping a pretty simple UIKit component for it to be used within a SwiftUI view. Context goes as follows:
- The component expects a UIImage as a parameter in its initializer but I wish to initialize it with a blank UIImage() and later update it with one downloaded async from the web with
Kingfisher
.
Wrapper code is the following:
struct WrappedView: UIViewRepresentable {
var viewModel: Model
func makeUIView(context: Context) -> HorizontalComponent {
HorizontalComponent(image: UIImage(), title: viewModel.title, subtitle: viewModel.subtitle)
}
func updateUIView(_ uiView: HorizontalComponent, context: Context) {
KingfisherManager.shared.retrieveImage(with: URL(string: "someImageUrl", completionHandler: { result in
switch result {
case .success(let value):
DispatchQueue.main.async {
//method from the UIView that simply updates the image of a UIImageview.
uiView.setImage(value.image)
}
case .failure(let error):
print("Error fetching image")
}
})
DispatchQueue.main.async {
uiView.setTitle(viewModel.title)
uiView.setSubtitle(viewModel.subtitle)
// hides non needed views, though for whatever reason it seems Im not on a MainThread context so it needs to be explicitly run on Main Thread else it has no effect.
uiView.roundedImageView.isHidden = true
uiView.circularImageView.isHidden = true
}
}
}
The SwiftUI View that uses this representable is pretty simple and goes as follows:
struct LandView: View {
private let models: [Model]
private let isLoading: Bool
init(models: [Model],
isLoading: Bool) {
self.models = models
self.isLoading = isLoading
}
var body: some View {
VStack {
if isLoading {
ShimmerView()
else {
WrappedView(viewModel: model[0])
}
}
}
The view that injects the state variables is the following:
struct HomeView: View {
@ObservedObject var viewModel: ViewModel
var body: some View {
VStack {
LandView(models: viewModel.cards, isLoading: viewModel.isLoading)
}
}
ViewModel:
class ViewModel: ObservableObject {
@Published private(set) var cards: [Model] = []
@Published private(set) var isLoading: Bool = true
//more functionality that actually handles the value of this variables ofc
}
What happens is that it works fine the first time the View is shown on screen, but when I toggle some sort of SwiftUI
state update from the VM and makeUIView
is called as well as updateUIView
, the view on screen resets to what is initialized on makeUIView and never actually does the changes from updateUiview
(such as hiding the isHidden properties from the views that are not needed, for example). The updateUIView method is called, though.
It seems that for whatever reason my wrapped view is reset to its initial state every time a SwiftUI update is triggered.