SwiftUI:在运行时访问EnvironmentObject access时出现线程错误
我有一个场景,有几个环境对象:SwiftUI:在运行时访问EnvironmentObject access时出现线程错误,swiftui,swiftui-environment,Swiftui,Swiftui Environment,我有一个场景,有几个环境对象: func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { // Get the managed object context from the shared persistent container. let context = (UIApplication.s
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Get the managed object context from the shared persistent container.
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
// Create the SwiftUI view and set the context as the value for the managedObjectContext environment keyPath.
// Add `@Environment(\.managedObjectContext)` in the views that will need the context.
let contentView = MainTabView()
//Inject Database repository
.environmentObject(DatabaseRepository())
.environmentObject(UserRepository())
.environmentObject(StockRepository(api: AlphaVantageAPI()))
.environment(\.managedObjectContext, context)
// Use a UIHostingController as window root view controller.
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window
window.makeKeyAndVisible()
}
}
在我的MainTabView中,我创建了如下选项卡:
struct MainTabView: View {
@EnvironmentObject var database: DatabaseRepository
@EnvironmentObject var userRepository: UserRepository
@EnvironmentObject var stockRepository: StockRepository
var viewModel = MainTabViewModel()
init() {
UITabBar.appearance().barTintColor = UIColor(named: "primary")
}
var body: some View {
TabView {
HomeView(viewModel: HomeViewModel(databaseRepository: database,
userRepository: userRepository,
stockRepository: stockRepository))
.tabItem {
Image("account_balance_wallet")
.renderingMode(.template)
Text("Home")
}.tag(0)
...
}.accentColor(.white)
}
}
在我的HomeVM中,我有以下代码:
class HomeViewModel: ObservableObject {
@Published var watchingVMs = [EquityPreviewCellViewModel]()
private let databaseRepository: DatabaseRepositoryProtocol
private let userRepository: UserRepositoryProtocol
private let stockRepository: StockRepositoryProtocol
init(databaseRepository: DatabaseRepositoryProtocol,
userRepository: UserRepositoryProtocol,
stockRepository: StockRepositoryProtocol) {
self.databaseRepository = databaseRepository
self.userRepository = userRepository
self.stockRepository = stockRepository
self.bind()
}
func bind() {
let allorders = databaseRepository
.allOrder(userID: userRepository.userID).share()
allorders
.assertNoFailure()
.compactMap({orders in
return orders?.reduce([Order](), { finalOrders, nextOrder in
var orders = [Order](finalOrders)
if !finalOrders.contains(where: { $0.symbol == nextOrder.symbol }) {
orders.append(nextOrder)
}
return orders
}).map({EquityPreviewCellViewModel(order: $0,
stockRepository: self.stockRepository,
userRepository: self.userRepository,
dataBaseRepository: self.databaseRepository)})
})
.receive(on: DispatchQueue.main)
.assign(to: &self.$watchingVMs)
我启动我的应用程序时发生以下崩溃:
线程1:EXC_BAD_指令(代码=EXC_I386_INVOP,子代码=0x0)
我想我没有很好地使用环境对象
,但我不明白为什么。可能是您想要的
.assign(to: \.watchingVMs, on: self)
或者(使用弱自我)
更新:将本地allorders
移动到属性以保持引用活动
func bind() {
let allorders = databaseRepository
.allOrder(userID: userRepository.userID).share()
allorders // << this one is destroyed on quit from bind
func bind(){
让allorders=databaseRepository
.allOrder(userID:userRepository.userID).share()
allorders/我认为您可能需要将此添加到main选项卡视图中
:
@Environment(\.managedObjectContext) var managedObjectContext
因为我们使用环境修饰符进行设置,并且您可能在simple@FetchRequest
s上执行保存、删除和其他一些任务
@Asperi建议的更改也是完全正确的,应该为此问题添加更改。这是因为方法签名不同:
.assign(to: \.watchingVMs, on: self)
也可能有线程问题导致EXC_BAD_ACCESS
,可能值得在此检查同步问题,即在同一主队列上执行提取请求。不,两者都会发生相同的崩溃。即使是空的接收器崩溃,请参阅更新的partEven move in属性也会使其仅在第一次运行时崩溃。我的解决方案是否有效?请告诉我。Fi最后,捕获失败的是我的assertNoFailure
。最后,与环境对象无关。
.assign(to: \.watchingVMs, on: self)