Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Saving CoreData to-many relationships in Swift

Tags:

I have a one-to-many relationship that looks like so,

coredata model

I've set up my model classes in a file to match:

import CoreData
import Foundation

class Board: NSManagedObject {
    @NSManaged var boardColor: String
    @NSManaged var boardCustomBackground: AnyObject?
    @NSManaged var boardID: String
    @NSManaged var boardName: String
    @NSManaged var lists: NSSet
}

class List: NSManagedObject {
    @NSManaged var listID: String
    @NSManaged var listName: String
    @NSManaged var board: Board
}

Because I'm fetching data from multiple JSON endpoints, I have to save my lists seperately from my boards. What I want to do is create/update a list for a board with a matching boardID.

Here's where I am after multiple attempts:

func saveList(boardID: String, listName: String, listID: String) {
    let request = NSFetchRequest(entityName: "Board")
    var error: NSError? = nil
    request.predicate = NSPredicate(format: "boardID like %@", boardID)
    let results: NSArray = context.executeFetchRequest(request, error: &error)
    if results.count > 0 {
        for result in results {
            let board = result as Board
            let list = NSEntityDescription.insertNewObjectForEntityForName("List", inManagedObjectContext: context) as List
            println("💃 want to save \(listName) in \(board.boardName)")
            board.lists.addListObject(lists)
            list.listName = listName
            list.listID = listID
        }
    }
}

Based on Defining CoreData Relationships in Swift and this, I tried to implement @Keenle's answer for define list objects inside a board:

import Foundation

extension Board {
    func addListObject(value:List) {
        var items = self.mutableSetValueForKey("lists");
        items.addObject(value)
    }

    func removeListObject(value:List) {
        var items = self.mutableSetValueForKey("lists");
        items.removeObject(value)
    }
}

However, I ran into the following error at board.lists.addListObject(lists): 'NSSet' does not have a member named 'addListObject'`

Instead of board.lists.addListObject(lists), I also tried board.lists.listName = listName as implied in this Obj-C example, but that sadly didn't work either.

(Also, The println output is correctly specifying the right board and list.)

Thanks in advance!

like image 376
Pirijan Avatar asked Aug 04 '14 20:08

Pirijan


People also ask

How do I save data in Core Data in swift 5?

Right-click on your project's folder in the project navigator and then New File… In the new window, type “data” in the top right corner, select Data Model, and press Next. Give it a name, and save it. Now, let's add all the necessary code to connect Core Data with our project.

What is relationship in Core Data?

A relationship's delete rule specifies how changes propagate across relationships when Core Data deletes a source instance. Select No Action to delete the source object instance, but leave references to it in any destination object instances, which you update manually.

Is Core Data thread safe?

Core Data is designed to work in a multithreaded environment. However, not every object under the Core Data framework is thread safe. To use Core Data in a multithreaded environment, ensure that: Managed object contexts are bound to the thread (queue) that they are associated with upon initialization.


2 Answers

In a one-to-many relationship, it is easier to set the "to-one" direction of the inverse relationships, in your case just

list.board = board

so that the extension methods are actually not needed here.

like image 152
Martin R Avatar answered Sep 28 '22 12:09

Martin R


You should invoke addListObject(...) on board object:

board.addListObject(list) // notice that we pass just one object

Additionaly, if you want to be able to add a set of lists to particular board object, you can enhance you Board class extension with methods that accept set of objects:

func addList(values: NSSet) {
    var items = self.mutableSetValueForKey("lists");
    for value in values {
        items.addObject(value)
    }
}

func removeList(values: NSSet) {
    var items = self.mutableSetValueForKey("lists");
    for value in values {
        items.removeObject(value)
    }
}
like image 44
Keenle Avatar answered Sep 28 '22 10:09

Keenle