Search code examples
swiftcore-datanspredicatensfetchrequest

Core data Fetch request on relationship properties


My app has a number of wordLists each of which contain a number of words. In one view controller a tableView lists the wordLists and then a sub view controller has a tableView with the words in it. The segue passes the wordList entity. But I cannot work out how to do a fetch request on the wordList passed to then get all the words. Error message is shown below. I need to do a fetch request rather than looking at properties so I can do a sort.

Thanks in advance for any help on this one....

The WordList entity has an attribute listName, and relationships: words, destination: Word, Inverse: wordList

The Word entity has an attribute wordName, wordIndex and relationships: wordList, destination: WordList, Inverse: words

My WordsViewController looks like:

class WordsViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UITextFieldDelegate  {

var coreDataStack: CoreDataStack = (UIApplication.sharedApplication().delegate as! AppDelegate).coreDataStack

var wordList: WordList?
var words = [Word]()
var word: Word?

override func viewDidLoad() {
    super.viewDidLoad()

    // set the title of the scene
    title = wordList?.listName

   // fetch all the words that are part of the wordList passed to this VC.
   let fetchRequest = NSFetchRequest(entityName: "Word")
    let wordListPredicate = NSPredicate(format: "word.wordList == '\(wordList)'") // GIVES AN ERROR SAYING UNABLE TO PARSE THE FORMAT STRING "word.wordList == 'Optional(<WordList:0x...

    let sortDescriptor = NSSortDescriptor(key: "wordIndex", ascending: true)
    fetchRequest.sortDescriptors = [sortDescriptor]

    fetchRequest.predicate = wordListPredicate

    do {
        if let results = try coreDataStack.managedObjectContext.executeFetchRequest(fetchRequest) as? [Word] {
            words = results
        }
    } catch {
        fatalError("There was an error fetching system person")
    }  
}

Solution

  • You cannot use string interpolation to build a predicate, use argument substitution instead. In your case (since var wordList: WordList? is an optional):

    if let theWordlist = wordlist {
        let wordListPredicate = NSPredicate(format: "wordList == %@", theWordlist)
    } else {
        // wordlist is nil ...
    }
    

    Note also that "word.wordList == " in the predicate should be "wordList == ", because "wordList" is the property of the "Word" entity.

    For more information, see Predicate Format String Syntax in the "Predicate Programming Guide".