Search code examples
iosswiftdowncast

Downcast set of type X that are subclass of of Y


Note: although the question has a CoreData example, it's not related to CoreData, it's just an example

We are working on a Swift project with CoreData as a caching layer.

We make use of Notifications in our mainViewController a lot to listen to the changes after our NSManagedObjectContext has new changes.

This is working great until we added new entities with the following hierarchy:

  • Entity Vehicle is a base class with some attributes.
  • Entity Car is a subclass of Vehicle with specific attributes and a toMany relationship to Human entity.
  • Entity Human is a base class with specific attributes, and it has a relationship the Car.

Entities

The problem is in the following:
when a new Car object is added, the notification fires, and in the mainViewController, we need to check if it's of type Car, like this:

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

The type downcast Set<Car> will never evaluate to true because the Set has elements of type Car and also Human.

What I want:
Check if the Set has NSManagedObject subclass of type Car or Human as I downcast it.

What I tried to do:
downcast it to NSManagedObject, and check if the Set contains Car by the adding the following where condition:
insertedObjects.contains(Car), but it has a compile-time error:

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

Let me know if you have any question instead of just downvoting.


Solution

  • Not sure about the type casting (I think I remember doing it the same way and it worked, although it was with an array), but checking if there is a car in the set is different:

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

    Or shorter (more concise) version of the same call:

    set.contains(where: { $0 is Car })