作为 Y 的子类的类型 X 的向下转换集

Downcast set of type X that are subclass of of Y

:虽然题中有CoreData例题,但与CoreData无关,只是例题

我们正在开发一个 Swift 项目,其中 CoreData 作为缓存层。

我们在 mainViewController 中大量使用 Notification 来收听 NSManagedObjectContext 有新变化后的变化。

在我们添加具有以下层次结构的新实体之前,这一直很有效:

问题如下:
当添加新的 Car 对象时,通知会触发,在 mainViewController 中,我们需要检查它是否属于 Car 类型,如下所示:

if let insertedObjects = notification.userInfo?[NSInsertedObjectsKey] as? Set<Car> {
    print("we have some cars") // this will never execute
}

类型向下转换 Set<Car> 永远不会计算为真,因为 Set 具有类型 CarHuman 的元素。

我想要的:
检查 Set 是否具有 CarHuman 类型的 NSManagedObject subclass,因为我向下转换它。

我尝试做的事情:
向下转换为 NSManagedObject,并通过添加以下 where 条件检查 Set 是否包含 Car
insertedObjects.contains(Car),但它有一个编译时错误:

Cannot convert value of type '(Car).Type' to expected argument type 'NSManagedObject'

如果您有任何问题,请告诉我,而不仅仅是投反对票。

不确定类型转换(我想我记得是用同样的方法做的,而且它起作用了,尽管它是用数组),但是检查集合中是否有汽车是不同的:

set.contains { (element) -> Bool in
    return element is Car
}

或同一调用的更短(更简洁)版本:

set.contains(where: { [=11=] is Car })

首先将插入的对象向下转换为Set<NSManagedObject>。 要检查是否插入了任何汽车,请使用

if let insertedObjects = notification.userInfo?[NSInsertedObjectsKey] as? Set<NSManagedObject> {

    if insertedObjects.contains(where: { [=10=] is Car }) {
        print("we have some cars")
    }

}

要将插入的汽车对象作为(可能为空的)数组获取, 使用 flatMap():

if let insertedObjects = notification.userInfo?[NSInsertedObjectsKey] as? Set<NSManagedObject> {

    let insertedCars = insertedObjects.flatMap { [=11=] as? Car }

}

你的方法

if insertedObjects.contains(Car)

无法编译,因为

func contains(_ member: Set.Element) -> Bool

期望元素类型的 实例 作为参数。 如上所示,您可以使用基于谓词的变体

func contains(where predicate: (Element) throws -> Bool) rethrows -> Bool

相反。