Tôi đang cố gắng tìm ra cách làm việc với các hoạt động không đồng bộ bằng cách sử dụng Kết hợp và SwiftUI.
Ví dụ: tôi có một HealthKitManager
lớp, trong số những thứ khác, xử lý yêu cầu ủy quyền cửa hàng y tế
final class HealthKitManager {
enum Error: Swift.Error {
case notAvailable
case authorisationError(Swift.Error)
}
let healthStore = HKHealthStore()
func getHealthKitData(for objects: Set<HKObjectType>, completion: @escaping (Result<Bool, Error>) -> Void) {
guard HKHealthStore.isHealthDataAvailable() else {
completion(.failure(.notAvailable))
return
}
self.healthStore.requestAuthorization(toShare: nil, read: objects) { completed, error in
DispatchQueue.main.async {
if let error = error {
completion(.failure(.authorisationError(error)))
}
completion(.success(completed))
}
}
}
}
được sử dụng như sau
struct ContentView: View {
let healthKitManager = HealthKitManager()
@State var showNextView = false
@State var showError = false
@State var hkError: Error?
let objectTypes = Set([HKObjectType.quantityType(forIdentifier: .bloodGlucose)!])
var body: some View {
NavigationView {
NavigationLink(destination: NextView(), isActive: $showNextView) {
Button("Show Next View") {
self.getHealthKitData()
}
}.navigationBarTitle("Content View")
}.alert(isPresented: $showError) {
Alert(title: Text("Error"), message: Text(hkError?.localizedDescription ?? ""), dismissButton: .cancel())
}
}
func getHealthKitData() {
self.healthKitManager.getHealthKitData(for: self.objectTypes) { result in
switch result {
case let .success(complete):
self.showNextView = complete
case let .failure(error):
self.hkError = error
self.showError = true
}
}
}
}
Những gì tôi muốn làm là sử dụng Kết hợp thay vì Result
đóng cửa. Tôi đoán điều gì đó như thế này
final class HealthKitManager: ObservableObject {
enum Error: Swift.Error {
case notAvailable
case authorisationError(Swift.Error)
}
@Published var authorisationResult: Result<Bool, Error>?
let healthStore = HKHealthStore()
func getHealthKitData(for objects: Set<HKObjectType>) {
guard HKHealthStore.isHealthDataAvailable() else {
self.authorisationResult = .failure(.notAvailable)
return
}
self.healthStore.requestAuthorization(toShare: nil, read: objects) { completed, error in
DispatchQueue.main.async {
if let error = error {
self.authorisationResult = .failure(.authorisationError(error))
return
}
self.authorisationResult = .success(completed)
}
}
}
}
Nhưng sau đó, không rõ làm thế nào để liên kết với các giá trị cho NavigationLink(isActive:)
và alert(isPresented:)
, và nhận được lỗi.
struct ContentView: View {
@ObservedObject var healthKitManager = HealthKitManager()
let objectTypes = Set([HKObjectType.quantityType(forIdentifier: .bloodGlucose)!])
var body: some View {
NavigationView {
NavigationLink(destination: NextView(), isActive: ????) { // How do I get this
Button("Show Next View") {
self.healthKitManager.getHealthKitData(for: self.objectTypes)
}
}.navigationBarTitle("Content View")
}.alert(isPresented: ????) { // or this
Alert(title: Text("Error"), message: Text(????.localizedDescription ?? ""), dismissButton: .cancel()) // or this
}
}
}
Tôi đoán điều đó @Published var authorisationResult: Result<Bool, Error>?
không đúng? Tôi có nên sử dụng Future / Promise
, cái gì khác?
Cập nhật
Tôi thấy có một cách khác để trình bày một cảnh báo
.alert(item: self.$error) { error in
Alert(title: Text(error.localizedDescription))
điều đó có nghĩa là tôi không cần Bool cho showError
(nó chỉ yêu cầu Error
đối tượng là Identifiable
)
@Published
cung cấp cho bạn một nhà xuất bản và tích hợp tự động với làm mới chế độ xem SwiftUI thông qua thuộc@ObservedObject
tính động. Bạn có thể sử dụng bất cứ thứ gì, nhưng hãy nghĩ về ưu và nhược điểm . Đó có phải là mục tiêu để làm cho những điều đơn giản trở nên phức tạp?