0

So I'm new to using SwiftUI. Normally I'd have the fetch request in the viewdidload method but not sure how to go about it now as the method doesn't seem to have an equivalent.

So I have a view where I'm passing a variable to another view like so

NavigationLink(destination: ItemAddView(series: series)) {
    Label("Add Item", systemImage: "plus")
}

I'm now wanting to use this variable in a predicate on a fetch request. The fetch request is setup as follows

struct ItemAddView: View {
@Environment(\.managedObjectContext) private var viewContext

@FetchRequest(
    sortDescriptors: [NSSortDescriptor(keyPath: \Item.name, ascending: true)],
    animation: .default)
private var items: FetchedResults<Item>

var series: Series

@State private var searchText = ""

var body: some View {
    List {
        ForEach(items) { item in
            NavigationLink(destination: ItemDetailView(item: item)) {
                Image(item.mainImage ?? "")
                    .renderingMode(.original)
                    .resizable()
                    .scaledToFit()
                    .frame(width: 100.0)
                Text("\(item.name ?? "Error")")
            }
        }
    }
    .searchable(text: $searchText)
    .onSubmit(of: .search) {
        items.nsPredicate = NSPredicate(format: "series = %@", series)
        if(!searchText.isEmpty) {
            items.nsPredicate = NSPredicate(format: "series = %@ AND amount = 0 AND name CONTAINS[cd] %@", series, searchText)
        }
    }
    .onChange(of: searchText) { _ in
        items.nsPredicate = NSPredicate(format: "series = %@", series)
        if(!searchText.isEmpty) {
            items.nsPredicate = NSPredicate(format: "series = %@ AND amount = 0 AND name CONTAINS[cd] %@", series, searchText)
        }
    }
    .navigationBarTitle("\(series.name ?? "Error") Add Items", displayMode: .inline)
    .onAppear() {
        items.nsPredicate = NSPredicate(format: "series = %@ AND amount = 0", series)
    }
}
}

I get an error if I use the predicate here

Cannot use instance member 'series' within property initializer; property initializers run before 'self' is available

I've taken to using the predicate in the onAppear method as such

.onAppear() {
    items.nsPredicate = NSPredicate(format: "series = %@ AND amount > 0", series)
}

But the issue is I'm seeing the full list before it then goes to the filtered request. What's the correct way of doing this?

Ceri Turner
  • 830
  • 2
  • 12
  • 36

1 Answers1

1

You just need to declare the variable in the header. You can then do the initialization in the init() and use the variable that is passed in. If you aren't subsequently needing series, you do not need to have any variable in the view to assign it to. Also, as you didn't post your full view, I had to guess at the type of series.

struct ItemAddView: View {
    @Environment(\.managedObjectContext) private var viewContext

    @FetchRequest private var items: FetchedResults<Item>


    init(series: Series) {
        let request = Item.fetchRequest(sortDescriptors: [NSSortDescriptor(keyPath: \Item.name, ascending: true)], predicate: NSPredicate(format: "series = %@ AND amount > 0", series), animation: .default)
        _items = FetchRequest(fetchRequest: request)

        // Initialize anything else that is necessary
    }

    ...
}
Yrb
  • 8,103
  • 2
  • 14
  • 44
  • The series is used elsewhere in the file so needs to be assigned in the view. Using your code I get an error "Argument passed to call that takes no arguments", that's on the let request line – Ceri Turner May 18 '22 at 20:48
  • That is an important detail that you left out. Please post the view that calls this. It really helps to post a [Minimal Reproducible Example (MRE)](https://stackoverflow.com/help/minimal-reproducible-example). – Yrb May 18 '22 at 20:59
  • Updated the post with the full view – Ceri Turner May 18 '22 at 21:15
  • Can you show how you put the `init()` in your code? The code you posted does not have my code in it. You can show it as an addition, after saying something like "Update:" so we can see the progression. – Yrb May 18 '22 at 21:21
  • Got it working in the end – Ceri Turner Jun 04 '22 at 15:35