2

我有这个场景有几个环境对象:

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_INSTRUCTION(代码=EXC_I386_INVOP,子代码=0x0)

在此处输入图像描述

我想我用得不好,environmentObject但我不明白为什么。

4

2 回答 2

0

可能你想要

.assign(to: \.watchingVMs, on: self)

或(使用弱自我)

.sink { [weak self] value in
   self?.watchingVMs = value
}

更新:将本地移动allorders到属性以保持引用有效

func bind() {
    let allorders = databaseRepository
        .allOrder(userID: userRepository.userID).share()
    allorders    // << this one is destroyed on quit from bind
于 2021-01-04T15:05:56.193 回答
0

我认为您可能需要将其添加到MainTabView

@Environment(\.managedObjectContext) var managedObjectContext

@FetchRequest因为我们使用环境修饰符来设置它,你可能会在 simple s之上进行保存、删除和其他一些任务。

@Asperi 建议的更改也是完全正确的,应该为这个问题添加。这是因为方法签名不同:

.assign(to: \.watchingVMs, on: self)

也可能有线程问题导致EXC_BAD_ACCESS,也许值得在这里检查同步问题,即在同一个主队列上执行获取请求。

于 2021-01-04T19:31:42.060 回答