Now I've asked chatgpt if there is a hack we can do to alleviate this problem by making write on the mainthreads but allow read to be from any thread. It came up with this solution:
import Foundation
class UserModel {
private var _name: String
private var _age: Int
private let queue = DispatchQueue.main // Queue to ensure writes happen on the main thread
init(name: String, age: Int) {
self._name = name
self._age = age
}
// Custom getter allows read access from any thread
var name: String {
return _name
}
var age: Int {
return _age
}
// Custom setter ensures writes happen on the main thread
func update(name: String, age: Int) {
if Thread.isMainThread {
self._name = name
self._age = age
} else {
queue.async {
self._name = name
self._age = age
}
}
}
}
@Observable
class UserViewModel {
private var _userModel: UserModel
private let queue = DispatchQueue.main
init(userModel: UserModel) {
self._userModel = userModel
}
// Custom getter for the UserModel allows reads from any thread
var userModel: UserModel {
return _userModel
}
// Custom setter ensures writes happen on the main thread
func updateUserModel(name: String, age: Int) {
if Thread.isMainThread {
_userModel.update(name: name, age: age)
} else {
queue.async {
self._userModel.update(name: name, age: age)
}
}
}
}
// NetworkManager can now read from any thread and only needs to jump to the main thread for writes
class NetworkManager {
func updateUserInfo(viewModel: UserViewModel) {
Task {
// Read values from UserModel without jumping to the main thread
let userName = viewModel.userModel.name
let userAge = viewModel.userModel.age
print("Making network call with userName: \(userName) and userAge: \(userAge)")
// Simulate network delay
try await Task.sleep(nanoseconds: 1_000_000_000)
// After the network call, update the UserModel on the main thread
viewModel.updateUserModel(name: "Jane Doe", age: 31)
}
}
}
// Example usage
let userModel = UserModel(name: "John Doe", age: 30)
let viewModel = UserViewModel(userModel: userModel)
let networkManager = NetworkManager()
// Calling from a background thread
Task {
await networkManager.updateUserInfo(viewModel: viewModel)
}
Essentially wrapping each state with an internal backing and then controlling read and write. Does this approach have any issues? I dont trust chatgpt.