Reputation: 17735
I have this scene with this several environmentObject:
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()
}
}
In my MainTabView, I have a tab created like this:
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)
}
}
In my HomeVM, i have this code:
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)
My I launch my application I have this crash:
Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
I supposed I am not well using environmentObject
but I can't see why.
Upvotes: 1
Views: 258
Reputation: 9935
I think you may need to add this to MainTabView
:
@Environment(\.managedObjectContext) var managedObjectContext
since we are setting this with an environment modifier, and you may be doing saving, deleting and some other tasks on top of simple @FetchRequest
s.
Also the changes as suggested by @Asperi are completely correct, and should be added for this issue. This one is since the method signature is different:
.assign(to: \.watchingVMs, on: self)
There may also be threading issues resulting in the EXC_BAD_ACCESS
, maybe worth checking for sync issues here, namely executing fetch requests on the same Main queue.
Upvotes: 0
Reputation: 258345
Probably you wanted
.assign(to: \.watchingVMs, on: self)
or (to use weak self)
.sink { [weak self] value in
self?.watchingVMs = value
}
Update: move local allorders
to property to keep reference alive
func bind() {
let allorders = databaseRepository
.allOrder(userID: userRepository.userID).share()
allorders // << this one is destroyed on quit from bind
Upvotes: 0