2

I saw same type of error but with different kind of code here, so I think it's better to ask a new question on this context. I have attempted to "find a specific entity" from core data by trying to pass a string variable (which use as a key to find that entity) called title into @FetchRequest. This is part of the code I have used

struct AccountMainPage: View {
    //*** User input ***
    var title: String

    //*** Core data enviroment initialisation ***
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
    @Environment(\.managedObjectContext) var managedObjectContext
    @FetchRequest(fetchRequest: Accounts.getSpecificAccounts(findTitle: title)) var fetchedAccount: FetchedResults<Accounts>


    var body: some View {
    //SOME CODE HERE
    }
}

The public class Accounts has the extension:

extension Accounts {
    static func getSpecificAccounts(findTitle: String) -> NSFetchRequest<Accounts> {
    let request: NSFetchRequest<Accounts> = Accounts.fetchRequest() as! NSFetchRequest<Accounts>

    let findDescriptor = NSPredicate(format: "title == %@",findTitle)

    request.predicate = findDescriptor

    return request
    }
}

However, the line with @FetchRequest(fetchRequest: Accounts.getSpecificAccounts(findTitle: title)) var fetchedAccount: FetchedResults<Accounts> has a syntax error:

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

Is there something wrong with my code?

np2314
  • 645
  • 5
  • 14

1 Answers1

2

@FetchRequest is dynamic property which is initialised, as any other property, before your AccountMainPage init is called, so self is not available yet, that is why you cannot use title property which is a member of self, and that is about what compiler error tells.

So here is a possible solution: we initialise fetch request property with stub request and then in init, which is called later, reinitialise it with real fetch request.

Here is an approach demo (all unrelated things cut):

struct ContentView: View {
    var title: String

    @Environment(\.managedObjectContext) var managedObjectContext
    @FetchRequest(fetchRequest: Accounts.fetchRequest()) var fetchedAccount: FetchedResults<Accounts>

    init(title: String) {
        self.title = title
        _fetchedAccount = FetchRequest<Accounts>(fetchRequest: Accounts.getSpecificAccounts(findTitle: title))
    }

...
Asperi
  • 228,894
  • 20
  • 464
  • 690
  • Thanks it works partially, what is the difference between `fetchedAccount` and `_fetchedAccount` and which one would I use in the `var body: some View {...}` section to call the entity inside? – np2314 Dec 04 '19 at 12:29
  • `_fetchedAccount` is a request, `fetchedAccount` is a response, so if you are about showing results, then you should use `fetchedAccount`. – Asperi Dec 04 '19 at 12:33
  • @Asperi is it possible to fetch just a single object from Core Data, For example: I don't have multiple objects of user profile, there is only single user profile and I would like to just get a single object, but I couldn't. I want to get user profile as a single object instead of array like [UserProfile]. I want to do something like this : @FetchRequest(entity: UserProfile.entity()) var userProfile: FetchedResult.... I don't know if that is possible – bona912 Oct 11 '20 at 12:14
  • Is this still the preferred method of customizing a FetchRequest's predicate based on a parameter passed to a view? I've been trying to use the new iOS 13 nsPredicate Dynamic Property in .onAppear() and find that the @FetchRequest's predicate gets set to nil after the first time SwiftUI updates the first View update. Anyone else seen this? – – Chuck H Jul 18 '21 at 03:35
  • Try this approach, you don't need to implement the init() thing. https://stackoverflow.com/questions/68530633/how-to-use-a-fetchrequest-with-the-new-searchable-modifier-in-swiftui – William Tong Dec 30 '21 at 08:55