CoreData OneToMany Error

I am working on learning CoreData, and part of that is figuring out how to handle one-to-many relationships. For practice, I am writing a simple app containing a list of people. Each person can have many books.

These are my entities

extension Person {

    @NSManaged var firstName: String?
    @NSManaged var lastName: String?
    @NSManaged var age: NSNumber?
    @NSManaged var personToBook: NSSet?

}

extension Books {

    @NSManaged var bookName: String?
    @NSManaged var bookISBN: String?
    @NSManaged var bookToPerson: Person?

}

The app has two lists, one for people and one for books. I have a segue set up, so that when I select a person, it goes to a book list, and displays the list of books. Books are added from the list of books. I have the prepareForSegue function on the people list set up to pass information to the books list.

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    let vc = segue.destinationViewController as! BooksController

    vc.person = fetchedResultsController.objectAtIndexPath(selectedIndex) as! Person
    vc.context = self.context
    vc.fetchedResultsController = self.fetchedResultsController
}

On the books list, there's an Add button that displays a UIAlertViewController that collects data about the book.

@IBAction func addItem(sender: UIBarButtonItem) {
    let alertController = UIAlertController(title: "Add Person", message: "Enter data to add a new book" , preferredStyle: .Alert)

    alertController.addTextFieldWithConfigurationHandler { (textField) in
        textField.placeholder = "Book Name"
        textField.keyboardType = .ASCIICapable
    }

    alertController.addTextFieldWithConfigurationHandler { (textField) in
        textField.placeholder = "ISBN"
        textField.keyboardType = .ASCIICapable
    }

    alertController.addAction(UIAlertAction(title: "Ok", style: .Default, handler: {
        alert -> Void in
        let entity = NSEntityDescription.entityForName("Books", inManagedObjectContext: self.context)
        let bookInstance = Books(entity:entity!, insertIntoManagedObjectContext: self.context)

        bookInstance.bookName = alertController.textFields?[0].text
        bookInstance.bookISBN = alertController.textFields?[1].text

        self.person.mutableSetValueForKey("personToBook").addObject(bookInstance)

        do {
            try self.context.save()
        }
        catch let error as NSError {
            print("Error saving a book \(error.localizedDescription)")
        }
    }))
    alertController.addAction(UIAlertAction(title: "Cancel", style: .Cancel, handler: nil))

    presentViewController(alertController, animated: true, completion: nil)
}

Everything is working fine for adding people. I can add, edit, and delete with no problems. I appear to be able able to add books in the manner above, but I get errors when the UITableView is trying to display the newly added book. The errors are:

2015-11-28 16:43:41.911 OneToMany[52183:2082686] _BSMachError: (os/kern) invalid capability (20) 2015-11-28 16:43:41.912 OneToMany[52183:2083078] _BSMachError: (os/kern) invalid name (15)

When I exit out to the people list and then come back in, the just added book is in the list. The added books do not show on the books UITableView until exiting and coming back in to the list.

I am not sure where this code is going wrong. Any suggestions?

Answers


The issue didn't have anything to do with CoreData, it had to do with my adding to Books from within the UIAlertAction closure. I updated my code like this:

    alertController.addAction(UIAlertAction(title: "Ok", style: .Default, handler: {
        alert -> Void in
        dispatch_async(dispatch_get_main_queue(), { () -> Void in
            let entity = NSEntityDescription.entityForName("Books", inManagedObjectContext: self.context)
            let bookInstance = Books(entity:entity!, insertIntoManagedObjectContext: self.context)

            bookInstance.bookName = alertController.textFields?[0].text
            bookInstance.bookISBN = alertController.textFields?[1].text

            self.person.mutableSetValueForKey("personToBook").addObject(bookInstance)

            do {
                try self.context.save()
                self.tableView.reloadData()
            }
            catch let error as NSError {
                print("Error saving a book \(error.localizedDescription)")
            }
        })
    }))

After this, the errors went away and the tableView reloaded.

I found this answer upon further searching stackoverflow for the errors.

I'm still not 100% sure that this is really the correct way to handle one to many relationships in CoreData, but it does seem to work.


Need Your Help

How do I check that a byte is sent successfully using the TCP protocol?

sockets tcp

I'm having a problem doing network programming. I'm using the TCP protocol to communicate between server and client. My code is working, but I as yet can't detect that the data is successfully sent...

Append text to stderr redirects in bash

bash exec stderr

Right now I'm using exec to redirect stderr to an error log with