Home > Net >  Value of type [ViewModel] has no member nsPredicate
Value of type [ViewModel] has no member nsPredicate

Time:04-05

I have a list of bookmarks stored with Core Data that i want to search through. But i'm getting this error next to vm.myBookmarks.nsPredicate = NSPredicate(value: true) in 'var query' below.

Value of type '[MyBookmarkViewModel]' has no member 'nsPredicate'

@ObservedObject var vm : MyBookmarksViewModel
@State private var searchText = ""

  ForEach(vm.myBookmarks) { myBookmark in

                    Text(myBookmark.name)
                    Text(myBookmark.url)          
            }
                .searchable(text: query)


var query: Binding<String> {
    Binding {
        searchText
    } set: { newValue in
        searchText = newValue
        if newValue.isEmpty {
            vm.myBookmarks.nsPredicate = NSPredicate(value: true)
        } else {
            vm.myBookmarks.nsPredicate = NSPredicate(format: "name CONTAINS[cd] %@", newValue)            }
    }
}


      

MyBookmarksViewModel

class MyBookmarksViewModel: NSObject, ObservableObject {
    
    @Published var myBookmarks = [MyBookmarkViewModel]()

    private let fetchedResultsController: NSFetchedResultsController<MyBookmark>
    private var context: NSManagedObjectContext
    
    init(context: NSManagedObjectContext){
        self.context = context
        self.fetchedResultsController = NSFetchedResultsController(fetchRequest: MyBookmark.all  , managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
        super.init()
        fetchedResultsController.delegate = self
        fetchAll()
        
        }
        ............

MyBookmarkViewModel

struct MyBookmarkViewModel: Identifiable, Hashable{
    
    init(myBM: MyBookmark) {
        self.myBM = myBM
        
    }
    private let myBM: MyBookmark
    
    var id: NSManagedObjectID {
        myBM.objectID
    }
    
    var name: String {
        myBM.name ?? ""
    }
}

MyBookmark

@objc(MyBookmark)
public class MyBookmark: NSManagedObject, BaseModel {
    static var all: NSFetchRequest<MyBookmark> {
        let request: NSFetchRequest<MyBookmark> = MyBookmark.fetchRequest()
        request.sortDescriptors = []
        return request
    }
    
}


extension MyBookmark {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<MyBookmark> {
        return NSFetchRequest<MyBookmark>(entityName: "MyBookmark")
    }

    @NSManaged public var name: String?
    @NSManaged public var url: String?

}

extension MyBookmark : Identifiable {

}

This is for a macOS app.

CodePudding user response:

nsPredicate belongs to the @FetchRequest property wrapper. But you are using NSFetchedResultsController.

Make the NSFetchedResultsController public

public let fetchedResultsController: NSFetchedResultsController<MyBookmark>

and assign the predicate to the controller

...
if newValue.isEmpty {
    vm.fetchedResultsController.fetchRequest.predicate = NSPredicate(value: true)
} else {
    vm.fetchedResultsController.fetchRequest.predicate = NSPredicate(format: "name CONTAINS[cd] %@", newValue)
}

Or shorter

vm.fetchedResultsController.fetchRequest.predicate = newValue.isEmpty 
    ? nil 
    : NSPredicate(format: "name CONTAINS[cd] %@", newValue)

If you don't want to make the controller public use a helper function in the view model.

  • Related