I have a model that inherits from another one. In the model, I have a few @Published
fields. The view where the model is getting used is used in a cell. The first time I create the view @Published
works fine. But the cell gets updated often with new data so I need to recreate the view with a new model. And here I have a problem. @Published
stops working (for instance highlighting on the video). And everything works fine if I get rid of the inheritance.
I found a similar issue (that was a SwiftUI bug) and also tried to use self.objectWillChange.send()
but it did not help.
Model:
final class DashboardWatchlistViewModel: DashboardTradableViewModel, ObservableObject {
@Published var isHighlighted = false
@Published var chartViewModel: AssetLineChartViewRepresentable.ViewModel?
........
init(.....) {
super.init()
}
}
Parent model:
class DashboardTradableViewModel {
// MARK: - Properties
// MARK: - Init
init(....) {
}
}
Creating the view(this part is getting called frequently):
func configure(with viewModel: DashboardWatchlistViewModel) {
print("Tag1 configure")
self.dashboardWatchlistView = DashboardWatchlistView(viewModel: viewModel)
self.viewModel = viewModel
viewModel.chartDataEvent.compactMap { $0 }
.receive(on: DispatchQueue.main)
.sink { [weak self] chartData in
viewModel.chartViewModel = AssetLineChartViewRepresentable.ViewModel(chartData: chartData, percentageChange: viewModel.percentageChange2)
}
.store(in: &cancellables)
}
View:
struct DashboardWatchlistView: View {
private struct Layout {
static let imageHeight: CGFloat = 40
static let imageWidth: CGFloat = 40
static let topPadding: CGFloat = 10
static let frameHeight: CGFloat = 69
static let cornerRadius: CGFloat = 9
static let scaleFactor: CGFloat = 1.0
}
@ObservedObject var viewModel: DashboardWatchlistViewModel
var body: some View {
VStack(alignment: .center) {
ZStack {
HStack(spacing: .designSystem(.extraSmall4)) {
HStack(spacing: .designSystem(.small)) {
KFImage(viewModel.logoURL)
.serialize(by: SVGCacheSerializer())
.setProcessor(SVGProcessor())
.scaleFactor(Layout.scaleFactor)
.resizable()
.placeholder {
Circle()
.fill(Color(viewModel.placeholderColor.isEmpty ? .gray : UIColor(hex: viewModel.placeholderColor)))
}
.frame(width: Layout.imageWidth, height: Layout.imageHeight)
.clipShape(RoundedRectangle(cornerRadius: Layout.imageWidth / 2))
.overlay(RoundedRectangle(cornerRadius: Layout.imageWidth / 2).stroke(.white, lineWidth: 2 / UIScreen.main.scale))
VStack(alignment: .leading, spacing: .designSystem(.extraSmall3)) {
HStack {
Text(viewModel.leftTitle).font(.subheadline).fontWeight(.semibold).lineLimit(1)
}
Text(viewModel.leftSubtitle).font(.caption2).foregroundColor(Color(ThemeManager.current.neutral50))
}
}
Spacer()
if let chartViewModel = viewModel.chartViewModel {
AssetLineChartViewRepresentable(viewModel: chartViewModel).frame(width: 65, height: 20)
}
VStack(alignment: .trailing, spacing: .designSystem(.extraSmall3)) {
percentChangeView(assetPercentChangeType: viewModel.assetPercentChangeType)
Text(viewModel.rightSubtitle).font(.caption2).foregroundColor(Color(ThemeManager.current.neutral50))
}
.padding(.leading, .designSystem(.medium))
}
.padding([.leading, .trailing])
if !viewModel.hideSeparator {
VStack {
Spacer()
Divider().padding(.leading)
}
}
}
}
.frame(height: Layout.frameHeight)
.background(
backgroundView(assetPositionType: viewModel.corners)
)
}
}