问题
i working the first time with relationships in core data. what i have now:
let appdelegate = NSApplication.shared().delegate as! AppDelegate
let context = appdelegate.persistentContainer.viewContext
// Create Person
let entityPerson = NSEntityDescription.entity(forEntityName: "Person", in: context)
let newPerson = NSManagedObject(entity: entityPerson!, insertInto: context)
newPerson.setValue("Max", forKey: "name")
// Create Book
let entityBooks = NSEntityDescription.entity(forEntityName: "Book", in: context)
let newBooks = NSManagedObject(entity: entityBooks!, insertInto: context)
newBooks.setValue("My Book", forKey: "title")
// Assign Book to Person
newPerson.setValue(NSSet(object: newBooks), forKey: "relationship")
This works fine. It creates a person and a book, which will assign to the created person.
But now the next problem: How can I assign a new book entry to an person, which is already available in core data?
UPDATE
This is my Core Data
Person.swift
@objc(Person)
public class Person: NSManagedObject {
}
extension Person {
@NSManaged public var name: String?
@NSManaged public var books: Book?
}
Book.swift
@objc(Book)
public class Book: NSManagedObject {
}
extension Book {
@NSManaged public var title: String?
}
I created the Person Max
let appdelegate = NSApplication.shared().delegate as! AppDelegate
let context = appdelegate.persistentContainer.viewContext
// Create Person
let entityPerson = NSEntityDescription.entity(forEntityName: "Person", in: context)
let newPerson = NSManagedObject(entity: entityPerson!, insertInto: context)
newPerson.setValue("Max", forKey: "name")
do {
try context.save()
} catch {}
Result in Core Data:
Then i created a book with the title "My Book" which should assign to Max
let appdelegate = NSApplication.shared().delegate as! AppDelegate
let context = appdelegate.persistentContainer.viewContext
// Create Book
let entityBook = NSEntityDescription.entity(forEntityName: "Book", in: context)
let newBook = NSManagedObject(entity: entityBook!, insertInto: context)
newBook.setValue("My Book2", forKey: "title")
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Person")
fetchRequest.predicate = NSPredicate(format: "name = %@", "Max")
do {
let result = try context.fetch(fetchRequest) as! [Person]
if let person = result.first {
person.setValue(NSSet(object: newBook), forKey: "books")
}
} catch { }
do {
try context.save()
} catch {}
Core Data Result
PERFECT !!
But now i will create a second book "My Book 2" which should assign to Max (with the same code above but with book title "My Book 2"
The result of core data
I hope you unterstand the problem :)
回答1:
You have to perform a fetch to check if the person is available.
Then assign the person to the book (to-one relationship) for example
let personName = "John"
let fetchRequest = NSFetchRequest<Person>(entityName: "Person")
let predicate = NSPredicate(format: "name == %@", personName)
fetchRequest.fetchLimit = 1
do {
let persons = try context.fetch(fetchRequest)
if let person = persons.first {
newBook.person = person
}
} catch {
print(error)
}
The code takes advantage of the Swift 3 generic types.
Edit:
The declaration of the NSManagedObject
subclasses are wrong.
According to your model Person
must be
extension Person {
@NSManaged public var name: String?
@NSManaged public var books: NSSet
}
and Books
must be
extension Book {
@NSManaged public var title: String?
@NSManaged public var person: Person?
}
Consider to make at least the name
and title
attributes non-optional.
PS: Since you are using NSManagedObject
subclasses you can use the property directly with dot notation rather then KVC
newPerson.name = "Max"
来源:https://stackoverflow.com/questions/43846527/swift-3-create-entry-with-relationship