Post not yet marked as solved
Post marked as unsolved with 1 replies, 193 views
I have implemented filtering on two lists in my app but for some reason cannot get this, the third, to work at all.
Inexperienced coder so please go easy on me!
Any guidance, suggestions, or pearls of wisdom appreciated in advance.
Am looking to have the filter on the list in the SelectProductsView...
@Environment(\.dismiss) var dismiss
@Environment(\.modelContext) private var modelContext
@Query var products: [Product]
@Bindable var order: Order
@State private var formType: EditProductImageFormType?
@State private var newProduct = false
@State private var showProductDetail: Bool = false
var body: some View {
NavigationStack {
if products.isEmpty {
ContentUnavailableView("Add your first Product", systemImage: "takeoutbag.and.cup.and.straw")
} else {
VStack {
List {
ForEach(products) { product in
HStack {
Text(product.name)
Spacer ()
if let orderProducts = order.products {
if orderProducts.isEmpty {
Button {
addRemove(product)
} label: {
Image(systemName: "xmark.square")
}
} else {
Button {
addRemove(product)
} label: {
Image(systemName: orderProducts.contains(product) ? "checkmark.circle" : "xmark.square")
}
}
}
.swipeActions(edge: .leading, allowsFullSwipe: true) {
Button {
showProductDetail.toggle()
} label: {
Image(systemName: "questionmark.bubble")
}
.tint(.orange)
}
}
}
.navigationTitle("Select Products")
.navigationBarTitleDisplayMode(.large)
}
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
Button {
formType = .new
} label: {
Image(systemName: "plus.circle")
}
.sheet(item: $formType) { $0 }
}
ToolbarItem(placement: .topBarLeading) {
Button("\(Image(systemName: "chevron.backward")) \(order.name)") {
dismiss()
}
}
}
}
}
}
func addRemove(_ product: Product) {
if let orderProducts = order.products {
if orderProducts.isEmpty {
order.products?.append(product)
} else {
if orderProducts.contains(product),
let index = orderProducts.firstIndex(where: {$0.id == product.id}) {
order.products?.remove(at: index)
} else {
order.products?.append(product)
}
}
}
}
// Add product to Shopping List
func add(_ product: Product) {
if let orderProducts = order.products {
if orderProducts.isEmpty {
order.products?.append(product)
} else {
order.products?.append(product)
}
}
}
// Remove product from Shopping List
func remove(_ product: Product) {
if let orderProducts = order.products {
if orderProducts.contains(product),
let index = orderProducts.firstIndex(where: {$0.id == product.id}) {
order.products?.remove(at: index)
}
}
}
// Filter & Sort initialisation
init(sortOrder: ProductSortOrder2, filterString: String) {
let sortDescriptors: [SortDescriptor<Product>] = switch sortOrder {
case .name:
[SortDescriptor(\Product.name)]
}
let predicate = #Predicate<Product> { product in
product.name.localizedStandardContains(filterString)
|| filterString.isEmpty
}
_products = Query(filter: predicate, sort: sortDescriptors)
}
}
Am getting a "Return from initializer without initializing all stored properties" error in Xcode on teh second to last line, after the init
I am calling this View from the EditOrderView...
struct EditOrderView: View {
@Environment(\.dismiss) private var dismiss
let order: Order
@State private var dateAdded = Date.distantPast
@State private var filterText = ""
@State private var name = ""
@State private var showProducts = false
@State private var sortOrder = ProductSortOrder2.name
var body: some View {
NavigationStack {
ZStack {
// background
Color(.systemGroupedBackground)
.ignoresSafeArea(.all)
// content
VStack {
HStack {
Button("Add Products"))") {
showProducts.toggle()
}
.frame(maxWidth: .infinity, alignment: .center)
.sheet(isPresented: $showProducts) {
// replaced SelectProductsView(order: order)
SelectProductsView(sortOrder: ProductSortOrder2.name, filterString: filterText, order: order)
.searchable(text: $filterText, prompt: Text("Filter on Product name"))
}
}
if let products = order.products {
OrderProductsListView(order: order, products: products)
}
}
.toolbar {
if changed {
Button {
order.name = name
dismiss()
} label: {
Image(systemName: "checkmark.circle")
.imageScale(.large)
}
}
}
.onAppear {
name = order.name
}
}
}
}
var changed: Bool {
name != order.name
}
}
enum ProductSortOrder2: LocalizedStringResource, Identifiable, CaseIterable {
case name = "alphabetcially by Name"
var id: Self {
self
}
}
Code was rearranged to stay within 7000 charachters...
Hoping someone can point me in the right direction!
Simon