Issue
This Content is from Stack Overflow. Question asked by Artiom
I am rewriting the existing UIKit cell with SwiftUI. ChartView
inside of it I wrapped with UIViewRepresentable
because it is out of scope right now to rewrite it as well. The data for the chart I am getting async and update the view once I have it. The viewModel for the chart I marked as @Published so SwiftUI knows when to update the view. The problem is the view flickers once the update is there.
View:
struct DashboardWatchlistView: View {
@ObservedObject var viewModel: DashboardWatchlistViewModel
var body: some View {
VStack(alignment: .center) {
ZStack {
HStack(spacing: 4) {
HStack(spacing: 16) {
Image(systemName: "person")
VStack(alignment: .leading, spacing: .designSystem(8) {
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)
}
}
}
}
}
}
ViewModel:
final class DashboardWatchlistViewModel: ObservableObject {
@Published var logoURL: URL?
@Published var leftTitle = ""
@Published var leftSubtitle = ""
@Published var rightTitle = ""
@Published var rightSubtitle = ""
@Published var percentageChange: Decimal = .zero
@Published var placeholderColor = ""
@Published var corners: Corners = .none
@Published var assetPercentChangeType: AssetPercentChangeType = .zero
@Published var hideSeparator = false
@Published var isHighlighted = false
@Published var chartViewModel: AssetLineChartViewRepresentable.ViewModel?
let chartDataEvent: AnyPublisher<BPChartData?, Never>
init(tradable: Tradable,
priceString: String,
percentageChange: Decimal,
corners: Corners,
hideSeparator: Bool,
assetPercentChangeType: AssetPercentChangeType,
chartDataEvent: AnyPublisher<BPChartData?, Never>) {
self.logoURL = tradable.logoURL
self.leftTitle = tradable.name
self.rightTitle = PercentageFormatter.default.string(from: abs(percentageChange))
self.leftSubtitle = tradable.symbol
self.rightSubtitle = priceString
self.percentageChange = percentageChange
self.placeholderColor = tradable.placeholderColor ?? ""
self.corners = corners
self.chartDataEvent = chartDataEvent
self.hideSeparator = hideSeparator
self.assetPercentChangeType = assetPercentChangeType
}
}
Cell
where I set the chartViewModel
:
final class DashboardWatchlistCell: UICollectionViewCell, HostingCell {
var hostingController: UIHostingController<DashboardWatchlistView>?
private var dashboardWatchlistView: DashboardWatchlistView?
private var viewModel: DashboardWatchlistViewModel?
private var cancellables = Set<AnyCancellable>()
override var isHighlighted: Bool {
didSet {
viewModel?.isHighlighted = isHighlighted
}
}
func configure(with viewModel: DashboardWatchlistViewModel) {
self.dashboardWatchlistView = DashboardWatchlistView(viewModel: viewModel)
self.viewModel = viewModel
// HERE I SET THE VIEWMODEL
viewModel.chartDataEvent.compactMap { $0 }
.receive(on: DispatchQueue.main)
.sink { chartData in
viewModel.chartViewModel = AssetLineChartViewRepresentable.ViewModel(chartData: chartData, percentageChange: viewModel.percentageChange)
}
.store(in: &cancellables)
}
func addHostedView(to parent: UIViewController) {
guard let dashboardWatchlistView = dashboardWatchlistView else { return }
addHostedView(dashboardWatchlistView, to: parent)
backgroundColor = .clear
}
}
Solution
This question is not yet answered, be the first one who answer using the comment. Later the confirmed answer will be published as the solution.
This Question and Answer are collected from stackoverflow and tested by JTuto community, is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.