I have the following code, which can be pasted right into an empty project:
struct Product: Decodable, Identifiable {
let id: Int
let title: String
}
@MainActor class ViewModel: ObservableObject {
@Published var products: [Product] = []
func refresh() async {
do {
let products = try await {
try await Task.sleep(for: Duration.seconds(2)) // Simulate network call
return [Product(id: 1, title: "iPhone")]
}()
self.products = products.sorted(by: self.sortClosure(_:_:))
} catch {
print(error.localizedDescription)
}
}
private func sortClosure(_ lhs: Product, _ rhs: Product) -> Bool {
lhs.id < rhs.id
}
}
struct ContentView: View {
@StateObject private var viewModel = ViewModel()
var body: some View {
List(self.viewModel.products) { product in
Text(product.title)
}
Button("Refresh") {
Task {
await self.viewModel.refresh()
}
}
}
}
The following line:
self.products = products.sorted(by: self.sortClosure(_:_:))
makes the compiler emit the following warning:
Converting function value of type '@MainActor (Product, Product) -> Bool' to '(Product, Product) throws -> Bool' loses global actor 'MainActor'
I could add nonisolated
to sortClosure(_:_:))
but that seems silly. I also tried conforming the struct Product
to the Sendable
protocol but that also does not shut up the warning.
Frankly, I just don't understand why the following works:
self.products = products.sorted(by: { $0.id < $1.id })
and the following would generate the above-mentioned warning:
self.products = products.sorted(by: self.sortClosure(_:_:))
What am I missing?