Search code examples
iosswiftrealm

How to declare optional class property with generic `Results`


I have a lot of Object subclasses which all of them conforms to some protocol (Transport for ex.) and I don't know which type of objects (Car or Bus for ex.) will be displayed, it depends on some parameters and therefore I want to have some generic computed value which can return Results of Objects based on Type enum value. Can I do that without casting Results to array?

protocol Transport { }
class Car: Object, Transport { }
class Bus: Object, Transport { }

// #1
var array: Array<Transport>? {
  return [Car(), Bus()]
}

// #2
var results: Results<Object>? {
  if displayCars {
    realm?.objects(Car.self)
  } else {
    realm?.objects(Bus.self)
  } 
}

№1 will be fine but №2 will not compile because: Cannot convert return expression of type 'Results<Car>?' to return type 'Results<Object>?'

Update

// Another example.
var objects: Results<Object>?

override func viewDidLoad() {
  super.viewDidLoad()

  if displayCars {
    objects = realm.objects(Car.self)
  }      

}

Compile error: Cannot assign value of type 'Results<Car>?' to type 'Results<Object>?'


Solution

  • Unfortunately, you will probably have to turn Results<Car> into [Car] in order for this to work. The built-in Swift collections are covariant, but any user-defined Swift generic type (including user-defined collections) is invariant. There's no way right now to specify otherwise.