在 Swift Core Data 中从一对多关系中获取对象
Posted
技术标签:
【中文标题】在 Swift Core Data 中从一对多关系中获取对象【英文标题】:Getting objects from to-many relationship in Swift Core Data 【发布时间】:2015-06-07 06:09:12 【问题描述】:在使用 Swift 在 Core Data 中使用多对多关系时,我遇到了一些困难。
我的数据模型
我想要做的是使用Country
的一个实例,然后显示该国家/地区公民的所有Contacts
。因为我一直在尝试这样做,所以我构建了一个 UITableViewController,它将显示该国的所有公民。但是,我在将实际的Contacts
脱离关系citizensOfCountry
时遇到了重大问题。这是我正在使用的代码(仅相关部分)。
class ShowingCitizensOfCountry: UITableViewController
var countryToShow: Country?
//This is a value that is passed by a prepareForSegue method
override func viewDidLoad()
//how do I get a list/set/other iterable object of Contacts?
//***Line in question***
let listOfPeople = countryToShow!.citizensOfCountry
for citizen in listOfPeople
println(citizen)//THIS IS NOT WORKING
所以,这根本行不通。现在在 for 循环中,我得到一个编译器错误,上面写着Type 'Contacts' does not conform to protocol 'Sequence Type'
。我对此不明白的是,它只是 Contact 类型……我认为这将是某种集合。所以,这不起作用,所以我尝试了这个。
let listOfPeople = countryToShow!.citizensOfCountry as! [Contacts]
这也不起作用,我收到错误'NSArray' is not a subtype of 'Contacts'
。接下来我尝试使用 NSSet 进行转换。
let listOfPeople = countryToShow!.citizensOfCountry as! NSSet<Contacts>
不幸的是,这也不起作用,我收到警告 Cast from 'Contacts' to unrelated type 'NSSet' always fails
和 Cannot specialize non-generic type 'NSSet'
。接下来我尝试了其他方法。我尝试使用valueForKey
方法。
let listOfPeople = countryToShow!.citizensOfCountry.valueForKey("name") as! Set<String>
这行得通!我可以只打印出该国所有公民的姓名。但是我不明白为什么。为什么当我使用 valueForKey("name")
时它可以工作,但我无法获得个人联系人?有没有更好的方法来做到这一点,我只是错过了?非常感谢任何关于为什么我无法从单个 Country
中获得 Contacts
集合的解释。谢谢。
【问题讨论】:
对不起,因为我真的很累,我无法阅读所有内容。但是从我读到的内容来看,你想得到一个应该是NSSet
的国家的公民。要做到这一点,您只需执行以下操作:yourArrayOfCountries.flatMap $0. citizensOfCountry.allObjects as! [Contacts]
。我会将其作为答案发布,以使其更易于阅读。
【参考方案1】:
对不起,因为我真的很累,我无法阅读所有内容。但是从我读过的内容来看,你想获得一个应该是 NSSet 的国家的公民。要做到这一点,你可以简单地做:
let contacts = yourArrayOfCountries.flatMap
$0.citizensOfCountry.allObjects as! [Contacts]
根据您的评论:
let contacts = countryToShow!.citizensOfCountry.allObjects as! [Contacts]
【讨论】:
这可能是我在做一些愚蠢的事情,但我写了let listOfPeople = countryToShow!.citizensOfCountry.flatMap $0.citizensOfCountry.allObjects as! [Contacts]
并收到错误'Contacts' does not have a member named 'flatMap'
这是你的意思吗?
您只能在阵列上使用flatMap
。您所做的是在NSSet
上,所以它不起作用。试试countryToShow!.flatMap $0.citizensOfCountry.allObjects as! [Contacts]
。我假设countryToShow
是Country
的数组。
是的,这也不起作用。 countryToShow
是一个 Country 对象,我正在尝试按照关系查找该国的公民。如果您关心,我使用您的代码得到的错误是'Country' does not have a member named 'flatMap'
抱歉,我假设 countryToShow 是一个数组。我会更新答案。
let contacts = countryToShow!.citizensOfCountry.allObjects as! [Contacts]
应该可以工作。让我知道:)【参考方案2】:
您的错误的原因是一对多关系导致NSSet
。您尝试通过这些集合进行迭代的所有尝试都应考虑到这一点。
更好的是实现NSFetchResultsController
,这是在表格视图中显示核心数据的标准方式。
countryToShow
的谓词
FRC 实施:
var fetchedResultsController: NSFetchedResultsController
if _fetchedResultsController != nil
return _fetchedResultsController!
let fetchRequest = NSFetchRequest(entityName: "Contact")
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "name", ascending: true)]
fetchRequest.predicate = NSPredicate(format:"countryOfOrigin = %@", self.countryToShow!)
let aFetchedResultsController = NSFetchedResultsController(
fetchRequest: fetchRequest, managedObjectContext: self.managedObjectContext!,
sectionNameKeyPath: nil, cacheName: nil)
_fetchedResultsController = aFetchedResultsController
var error: NSError? = nil
if !_fetchedResultsController!.performFetch(&error)
NSLog("%@", error!)
return _fetchedResultsController!
var _fetchedResultsController: NSFetchedResultsController? = nil
我把 Contacts 改成了更合适的单数。
【讨论】:
那么在这个解决方案中我什至会使用citizensOfCountry
关系吗?还是我只是根据他们的countryOfOrigin
关系过滤所有联系人?
是一样的,因为它们是反向关系。因为您使用的是Contacts
实体,所以您将使用countryOfOrigin
。我将修改我的答案,向您展示它是如何完成的。
只是为了我自己的好奇心,如果我已经找到了Country
,那么使用citizensOfCountry
关系找到Contacts
会不会更有效,或者它会是一样吗?
原则上是的。但是,您无法将获取的结果控制器用于您的表格视图,并获得所有额外的好处。以上是关于在 Swift Core Data 中从一对多关系中获取对象的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Swift 中将 Core Data 与 Cloudkit 和许多设备同步