2014-07-15 97 views
23

我有一個NSManagedObject類如何在Swift中分配CoreData多對多關係?

class Disease: NSManagedObject { 
    @NSManaged var diseaseId: String 
    @NSManaged var diseaseName: String 
    @NSManaged var dogBreed: NSSet 
} 

如何添加到dogBreed一個新的關係?如果我將var類型更改爲NSMutableSet,則更改不會保存到數據庫。有任何想法嗎?

+0

更多信息http://stackoverflow.com/questions/24146524/setting-an-nsmanagedobject-relationship-in-swift – DogCoffee

+0

對於其他人,因爲他們要學習如何在覈心數據使用關係是找到這個問題,我終於找到了這個教程:[核心數據和Swift:關係和更多的獲取](http://code.tutsplus.com/tutorials/core-data-and-swift-relationships-and-more-fetching--cms- 25070) – Wraithbone

回答

20

作爲Xcode的7和SWIFT 2.0的,所述release note 17583057狀態:

的NSManaged屬性可以與方法以及 屬性被用於訪問核心數據的自動生成 密鑰 - 符合值編碼的多對多訪問器。

@NSManaged var employees: NSSet 

@NSManaged func addEmployeesObject(employee: Employee) 
@NSManaged func removeEmployeesObject(employee: Employee) 
@NSManaged func addEmployees(employees: NSSet) 
@NSManaged func removeEmployees(employees: NSSet) 

這些可以在你的NSManagedObject子類中聲明。(17583057)

所以,你只需要聲明下面的方法和CoreData會照顧其餘的:

@NSManaged func addDogBreedsObject(dogBreed: DogBreed) 
@NSManaged func removeDogBreedsObject(dogBreed: DogBreed) 
@NSManaged func addDogBreeds(dogBreeds: NSSet) 
@NSManaged func removeDogBreeds(dogBreeds: NSSet) 
+1

非常感謝! + 100 – DogCoffee

+1

這可能很奇怪,但是Swift如何知道如何照顧其餘的?你不指定函數必須添加哪些設置? – Emptyless

+2

@Emptyless這與Swift無關。這些方法是由CoreData生成的,它實際上是NSManaged類的一部分。上面的答案只是解釋了用Swift這樣做的正確方法。這與在UIViewControllers中聲明IBOutlets非常相似,並且你問Swift如何知道如何將它鏈接到Storyboard(它不是Swift,它是UIKit) – Nycen

18

由於嚴格的類型系統,Swift無法生成動態運行時訪問器。您可以創建一個擴展Disease類和手動添加錯過方法,這裏是代碼:

extension Disease { 
    func addDogBreedObject(value:DogBreed) { 
     var items = self.mutableSetValueForKey("dogBreed"); 
     items.addObject(value) 
    } 

    func removeDogBreedObject(value:DogBreed) { 
     var items = self.mutableSetValueForKey("dogBreed"); 
     items.removeObject(value) 
    } 
} 

備註:

我建議你創建單獨的文件擴展名Disease+CoreData.swift,這將有助於保持您在重新生成CoreData模型時覆蓋您的代碼。

在一個託管對象中創建關係就足夠了,第二個託管對象將通過反向引用進行更新。 (與Objective-C相同)

重要事項:爲了使其完成所有工作,您應該驗證CoreData模型中的實體的類名是否包含模塊名稱。例如。 MyProjectName.Disease

回答啓發:Setting an NSManagedObject relationship in Swift

+1

我發現這段代碼不適用於我的應用程序,而沒有在適當的鍵值觀察代碼中包裝設置過程,以改變self.willChangeValueForKey(「key」,withSetMutation:,usingObjects:)和相應的didChangeValueForKey方法。沒有這種報道,各種各樣的奇怪和顯然無關的錯誤。 – Ash

+0

好點。我將測試您的建議,並在回到我的開發桌面時添加到答案中。 – Keenle

10

如果你正在尋找一種簡單的方法,只要使用此。

import CoreData 
extension NSManagedObject { 
    func addObject(value: NSManagedObject, forKey: String) { 
     var items = self.mutableSetValueForKey(forKey); 
     items.addObject(value) 
    } 
} 

實施:

department.addObject(section, forKey: "employees") 

而不是寫在需要它的每一個NSManageObject類相同的方法。

+0

啊哈 - 我喜歡這個解決方案。整齊。 –

2

作爲@Naz的擴展。並結合@Ash的評論。我發現的唯一的工作解決方案的Xcode 6.3.1

import CoreData 

extension NSManagedObject { 
    func addObject(value: NSManagedObject, forKey: String) { 
     self.willChangeValueForKey(forKey, withSetMutation: NSKeyValueSetMutationKind.UnionSetMutation, usingObjects: NSSet(object: value) as Set<NSObject>) 
     var items = self.mutableSetValueForKey(forKey); 
     items.addObject(value) 
     self.didChangeValueForKey(forKey, withSetMutation: NSKeyValueSetMutationKind.UnionSetMutation, usingObjects: NSSet(object: value) as Set<NSObject>) 
    } 
} 

你必須調用willChange和didChange處理程序,以對象中正確添加到斯威夫特一個一對多的關係。

myManagedObject.addObject(value, forKey: "yourKey") 
4

其實你可以這樣寫:

@NSManaged var dogBreed: Set<DogBreed> 

,並使用直接使用的方法insertremove

2

@Nycen具有的Xcode 7與現在自動實現的方法最好的解決方案,但請注意,NSOrderedSet問題幾乎令人難以置信依然存在(見this question),因此,如果使用的是您關係的NSOrderedSet而不是NSSet的你仍然會需要使用解決方法。

(我會評論,而不是發佈新的答案,但是我缺少點我)

+0

我不能相信這仍然是一個錯誤。也許在一個星期左右,他們會在WWDC上修復它。 –

1

如果你需要使用一個NSOrderedSet代替NSSet,我一直在使用下面的代碼,使得它更容易獲取NSMutableOrderedSet添加,插入和刪除對象的方法。

@NSManaged private var myOrderedSet: NSOrderedSet 

var myMutableOrderedSet: NSMutableOrderedSet { 
    return self.mutableOrderedSetValueForKey("myOrderedSet") 
}