3

I'm having trouble figuring out exactly what kind of argument list Swift is expecting here, because I am getting an error when I call "filter" on a swift array.

Here is my code:

func setDefaultBook()
{
    var book: Book

    let fetchRequest: NSFetchRequest<Book> = Book.fetchRequest()
    if let fetchResults = try? managedObjectContext.fetch(fetchRequest) {
        book = fetchResults.filter { $0.title == defaultBookTitle }
    }

    ...
}

A book is an NSManagedObject, and a book's title is a simple String property - an @NSManaged var. There is nothing special about the title here, and there's nothing to indicate that checking a title would throw. However, I get an error on the filter line that says:

"Cannot invoke 'filter' with an argument list of type '((Book) throws -> Bool)'

Clearly I'm missing something, because this comparison doesn't look to me like it would ever throw. I've tried a couple of other ways of doing this, and I keep getting the same error.

Building out the closure like so doesn't help:

book = fetchResults.filter { book in
    book.title == defaultBookTitle
}

And setting a predicate to do the same thing doesn't help either:

let predicate: (Book) -> Bool = { $0.title == self.defaultBookTitle }
book = fetchResults.filter(predicate)

I keep getting the same error as before.

Anyone have any idea why swift thinks that the argument here is (Book) throws -> Bool instead of just (Book) -> Bool?

Has anyone run into this error before? Any suggestions to fix it are appreciated.

1 Answer 1

6

The error message might be misleading. The result of filter is always an array

var books = [Book]()

let fetchRequest: NSFetchRequest<Book> = Book.fetchRequest()
if let fetchResults = try? managedObjectContext.fetch(fetchRequest) {
    books = fetchResults.filter { $0.title == defaultBookTitle }
}

But why not let Core Data filter the records:

var books = [Book]()

let fetchRequest: NSFetchRequest<Book> = Book.fetchRequest()
fetchRequest.predicate = NSPredicate(format:"title = %@", defaultBookTitle)
do {
   books = try managedObjectContext.fetch(fetchRequest)
} catch {
  print(error)
}
Sign up to request clarification or add additional context in comments.

2 Comments

Good answer on both counts. Some follow-ups: file bugs if you see compiler messages that need improving. And it's just about always better to let Core Data do filtering like this, because searching/filtering in the database is much cheaper than doing it on fetched/instantiated objects.
You are correct in that it was a misleading error message; unfortunately I focused on that instead of what the actual return was. Thank you for your help.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.