I want to update contentview Text when currentStatus change, but when run MLModel to load the model, it print 'loading resources...' but the currentStatus is not update the Text in ContentView,I try add DispatchQueue.main.async, but still not working
ContentView.swift
struct ContentView: View {
@StateObject var model = Content.ViewModel()
var body: some View {
VStack {
Text(model.currentStatus)
.multilineTextAlignment(.center)
.padding(.horizontal)
}
.padding()
.onAppear {
model.inited()
}
}
}
ContentModel.swift
class ContentModel: ObservableObject {
@Published var currentStatus: String = "init..."
func inited() {
currentStatus = "loading resources..."
print("currentStatus: \(self.currentStatus)")
guard let path = Bundle.main.path(forResource: "Unet", ofType: "mlmodelc", inDirectory: "split") else {
fatalError("Fatal error: failed to find the CoreML model.")
}
let resourceURL = URL(fileURLWithPath: path)
let config = MLModelConfiguration()
config.computeUnits = .cpuAndGPU
var loadedModel: MLModel?
do {
loadedModel = try MLModel(contentsOf: resourceURL, configuration: config)
} catch {
print(error)
}
currentStatus = "complete"
print("currentStatus: \(self.currentStatus)")
}
}
Solution using asyncAfter, but the code look terrible @_@!!!
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
let startTime = Date()
self.pipeline!.textEncoder.prewarmResources { result in
switch result {
case .success:
self.currentStatus = String(format: "textEncoder took %.2f seconds.", Date().timeIntervalSince(startTime))
case .failure(let error):
print("Error:", error)
}
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
let startTime = Date()
self.pipeline!.unet.prewarmResources { result in
switch result {
case .success:
self.currentStatus = String(format: "unet took %.2f seconds.", Date().timeIntervalSince(startTime))
case .failure(let error):
print("Error:", error)
}
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
let startTime = Date()
self.pipeline!.decoder.prewarmResources { result in
switch result {
case .success:
self.currentStatus = String(format: "decoder took %.2f seconds.", Date().timeIntervalSince(startTime))
case .failure(let error):
print("Error:", error)
}
}
}
}
}
It should be @StateObject, not @ObservedObject. And consider putting ContentModel definition into an extension of Model, so instead of having
you will have:
I believe it makes the code more readable but YMMV.