I am having trouble building my app because this error always pops up.
Fatal error: No ObservableObject of type ModelData found. A View.environmentObject(_:) for ModelData may be missing as an ancestor of this view.
I hope that you can help me. Below is the code that would be involved with this issue.
Model Data -
import Foundation
import Combine
final class ModelData: ObservableObject {
@Published var appleos: [AppleOS] = load("appleosData.json")
var features: [AppleOS] {
appleos.filter { $0.isFeatured }
}
var categories: [String: [AppleOS]] {
Dictionary(
grouping: appleos,
by: { $0.category.rawValue }
)
}
}
func load<T: Decodable>(_ filename: String) -> T {
let data: Data
guard let file = Bundle.main.url(forResource: filename, withExtension: nil)
else {
fatalError("Couldn't find \(filename) in main bundle.")
}
do {
data = try Data(contentsOf: file)
} catch {
fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
}
do {
let decoder = JSONDecoder()
return try decoder.decode(T.self, from: data)
} catch {
fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
}
}
AppleOSList -
import SwiftUI
struct AppleOSList: View {
@EnvironmentObject var modelData: ModelData
@State private var showFavoritesOnly = false
@State private var filter = FilterCategory.all
@State private var selectedAppleOS: AppleOS?
enum FilterCategory: String, CaseIterable, Identifiable {
case all = "All"
case operatingsystems = "Apple's Operating Systems"
var id: FilterCategory { self }
}
var filteredAppleOS: [AppleOS] {
modelData.appleos.filter { appleos in
(!showFavoritesOnly || appleos.isFavorite)
&& (filter == .all || filter.rawValue == appleos.category.rawValue)
}
}
var title: String {
let title = filter == .all ? "AppleOS" : filter.rawValue
return showFavoritesOnly ? "Favorite \(title)" : title
}
var index: Int? {
modelData.appleos.firstIndex(where: { $0.id == selectedAppleOS?.id })
}
var body: some View {
NavigationView {
List(selection: $selectedAppleOS) {
ForEach(filteredAppleOS) { appleos in
NavigationLink {
AppleOSDetail(appleos: appleos)
} label: {
AppleOSRow(appleos: appleos)
}
.tag(appleos)
}
}
.navigationTitle(title)
.frame(minWidth: 300)
.toolbar {
ToolbarItem {
Menu {
Picker("Category", selection: $filter) {
ForEach(FilterCategory.allCases) { category in
Text(category.rawValue).tag(category)
}
}
.pickerStyle(.inline)
Toggle(isOn: $showFavoritesOnly) {
Text("Favorites only")
}
} label: {
Label("Filter", systemImage: "slider.horizontal.3")
}
}
}
Text("Select an OS")
}
.focusedValue(\.selectedAppleOS, $modelData.appleos[index ?? 0])
}
}
struct AppleOSList_Previews: PreviewProvider {
static var previews: some View {
AppleOSList()
.environmentObject(ModelData())
}
}