Swift и CoreData, проблемы с отношениями (NSSet) - [NSSet intersectsSet:]: аргумент набора не является NSSet
Я пытался понять, как добавлять объекты в отношения, используя CoreData и Swift. Я в растерянности, я не понимаю, почему мой код не работает. Я пытаюсь добавить "Событие" в "Команду". Я не могу найти разницу между принятыми ответами (что должно работать) и моим кодом (что не работает).
Teams.swift:
import Foundation
import CoreData
class Teams: NSManagedObject {
@NSManaged var teamName: String
@NSManaged var matches: NSSet
}
extension Teams {
func addEventToTeam(event:Event) {
//self.mutableSetValueForKeyPath("matches").addObject(event)
var matchez: NSMutableSet
matchez = self.mutableSetValueForKey("matches")
matchez.addObject(event)
//var manyRelation = self.valueForKeyPath("matches") as NSMutableSet
//manyRelation.addObject(event)
}
func getTeamName() -> String {
return teamName
}
}
Код вызова (из представления конфигурации):
import UIKit
import CoreData
class DetailViewController: UIViewController, NSFetchedResultsControllerDelegate {
var managedObjectContext: NSManagedObjectContext? = nil
@IBOutlet weak var detailDescriptionLabel: UILabel!
var detailItem: AnyObject? {
didSet {
// Update the view.
self.configureView()
}
}
func configureView() {
// Update the user interface for the detail item.
if let detail: Event = (self.detailItem as? Event) {
//if let detail: AnyObject = self.detailItem {
if let label = self.detailDescriptionLabel {
label.text = detail.valueForKey("timeStamp").description
self.insertNewObject(self);
label.text = String(detail.getNumberOfTeams())
//detail.getTeams().
var hej: Array<Teams>
hej = detail.getTeams()
label.text = "tjosan"
for tmpTeam : Teams in hej {
label.text = label.text + ", " + tmpTeam.getTeamName()
}
}
}
if true {
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.configureView()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
var fetchedResultsController: NSFetchedResultsController {
if _fetchedResultsController != nil {
return _fetchedResultsController!
}
let fetchRequest = NSFetchRequest()
// Edit the entity name as appropriate.
let team = NSEntityDescription.entityForName("Teams", inManagedObjectContext: self.managedObjectContext)
fetchRequest.entity = team
// Set the batch size to a suitable number.
fetchRequest.fetchBatchSize = 20
// Edit the sort key as appropriate.
let sortDescriptor = NSSortDescriptor(key: "teamName", ascending: false)
let sortDescriptors = [sortDescriptor]
fetchRequest.sortDescriptors = [sortDescriptor]
// Edit the section name key path and cache name if appropriate.
// nil for section name key path means "no sections".
let aFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.managedObjectContext, sectionNameKeyPath: nil, cacheName: "Master")
aFetchedResultsController.delegate = self
_fetchedResultsController = aFetchedResultsController
var error: NSError? = nil
if !_fetchedResultsController!.performFetch(&error) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
//println("Unresolved error \(error), \(error.userInfo)")
abort()
}
return _fetchedResultsController!
}
var _fetchedResultsController: NSFetchedResultsController? = nil
func insertNewObject(sender: AnyObject) {
let context = self.fetchedResultsController.managedObjectContext
let team = self.fetchedResultsController.fetchRequest.entity
let newManagedObject = NSEntityDescription.insertNewObjectForEntityForName(team.name, inManagedObjectContext: context) as Teams
// If appropriate, configure the new managed object.
// Normally you should use accessor methods, but using KVC here avoids the need to add a custom class to the template.
newManagedObject.setValue("Lagur Namnurk", forKey: "teamName")
newManagedObject.addEventToTeam(self.detailItem as Event)
// Save the context.
var error: NSError? = nil
if !context.save(&error) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
//println("Unresolved error \(error), \(error.userInfo)")
abort()
}
}
}
Сообщение об ошибке:
2014-08-13 18:38:46.651 Score Calculator 2[10538:829319] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSSet intersectsSet:]: set argument is not an NSSet'
*** First throw call stack:
(
0 CoreFoundation 0x00000001028a53e5 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x00000001043b8967 objc_exception_throw + 45
2 CoreFoundation 0x000000010280fc6c -[NSSet intersectsSet:] + 940
3 Foundation 0x0000000102d0c4a6 NSKeyValueWillChangeBySetMutation + 156
4 Foundation 0x0000000102c804fa NSKeyValueWillChange + 386
5 Foundation 0x0000000102d0c3fb -[NSObject(NSKeyValueObserverNotification) willChangeValueForKey:withSetMutation:usingObjects:] + 310
6 CoreData 0x00000001024178d7 -[NSManagedObject(_NSInternalMethods) _includeObject:intoPropertyWithKey:andIndex:] + 551
7 CoreData 0x0000000102418294 -[NSManagedObject(_NSInternalMethods) _maintainInverseRelationship:forProperty:forChange:onSet:] + 276
8 CoreData 0x0000000102416ef2 -[NSManagedObject(_NSInternalMethods) _didChangeValue:forRelationship:named:withInverse:] + 562
9 Foundation 0x0000000102c835d6 NSKeyValueNotifyObserver + 356
10 Foundation 0x0000000102c827fd NSKeyValueDidChange + 466
11 Foundation 0x0000000102d0c7ee -[NSObject(NSKeyValueObserverNotification) didChangeValueForKey:withSetMutation:usingObjects:] + 118
12 CoreData 0x00000001024180b0 -[NSManagedObject didChangeValueForKey:withSetMutation:usingObjects:] + 80
13 CoreData 0x000000010242fa11 -[_NSNotifyingWrapperMutableSet addObject:] + 161
редактировать: пара разъяснений. Команды и соревнования имеют неупорядоченные отношения между несколькими.
2 ответа
Yesss!! Я нашел ответ!
Я создал новую функцию в классе Events.swift (другая сторона отношений).
Я написал следующий код:
import Foundation
import CoreData
class Event: NSManagedObject {
@NSManaged var timeStamp: NSDate
@NSManaged var teams: NSSet
}
extension Event {
func addTeamToEvent(team:Teams) {
var teamz = self.mutableSetValueForKey("teams")
teamz.addObject(team)
}
func getNumberOfTeams() -> Int {
return self.teams.count;
}
func getTeams() -> [Teams] {
var tmpsak: [Teams]
tmpsak = self.teams.allObjects as [Teams]
tmpsak = self.teams.allObjects as [Teams]
return tmpsak
}
}
который я думал не было связано. Однако переименование getTeams в getTeamsAsArray устранило проблему. Я предполагаю, что CoreData при заполнении другого конца отношения использует встроенную функцию getTeams() (так как другой класс назывался Teams). Я случайно преодолел (?) Это, заставляя это терпеть неудачу.
Спасибо за ваши предложения, и я надеюсь, что это может быть полезно для кого-то еще!
На несколько связанном примечании ошибка с похожими симптомами была обнаружена несколько лет назад (и, похоже, все еще присутствует), которая проявляется в автоматически сгенерированном коде при использовании упорядоченных отношений " многие ко многим".
Если вы используете целевые сгенерированные подклассы NSManagedObject, они включают в себя пользовательские методы для добавления одного объекта - я думаю, что они опробованы и проверены и кажутся лучше, чем то, что в настоящее время существует для swift.
Теоретически вам просто нужно установить новый набор с любым новым набором, который вы создали. Один из вариантов будет:
var matchobjs = matches.allObjects as [Event]
matchobjs.append(event)
matches = NSSet(array: matchobjs)
Однако ошибка выглядит очень похоже на этот пост:
Что для меня похоже на то, что снова происходит что-то подозрительное с отношениями многие ко многим...