Saturday, July 08, 2017
Type Erasure
Say that I have a view model that has a reference to a data source object generated by another object like a factory. In my view model I would have a property that is typed as AnyDataSource. I also have a property that is of type FRCDataSource, this is the object that will be wrapped in the AnyDataSource object.
class AddToDoViewModel {
var dataSource : AnyDataSource<Item>!
var frcDataSource : FRCDataSource<Item>!
FRCDataSource is defined as :
class FRCDataSource<T: NSManagedObject> : DataSourceProtocol {
var fetchedResultsController : NSFetchedResultsController<T>!
init(fetchedResultsController: NSFetchedResultsController<T>) {
self.fetchedResultsController = fetchedResultsController
}
}
The FRCDataSource class is a wrapper around an NSFetchedResultsController type. The generic type constraint on FRCDataSource limits the type of T to be an object that derives from NSManagedObject. Also note that FRCDataSource is specialized by the same type as NSFetchedResultsController. To create an FRCDataSource we do the following in reloadData()
func reloadData() {
self.frcDataSource = FRCDataSource(fetchedResultsController:self.fetchedResultsController)
}
We create an FRCDataSource, passing in the NSFetchedResultsController class property. Now our frcDataSource property is set to a FRCDataSource instance that internally stores a NSFetchedResultsController instance. In this case, I am creating an instance of FRCDataSource directly, although I could easily delegate this responsibility to another object which would create and return an FRCDataSource.
Once I’ve created an FRCDataSource object from the NSFetchedResultsController, I can now add a method that will create an AnyDataSource derived object and store it in the dataSource property of the view model:
func createDataSource<T: DataSourceProtocol>(dataSource: T) where T.DataSourceItem == Item
{
self.dataSource = AnyDataSource(dataSource)
}
The createDataSource() takes an object that adopts the DataSourceProtocol, creates an AnyDataSource object and sets the dataSource property. There are a few things to take note of here:
- The createDataSource method is a generic method and is specialized by an object that must adopt DataSourceProtocol. The input parameter dataSource is of the specialized type.
A generic constraint is specified which constrains the DataSourceItem associated type of the input parameter to be of type Item. This is done to make sure that the type of the dataSource property matches the type returned by the AnyDataSource(dataSource) init call.
Now we just have to pass in the frcDataSource property to the createDataSource() method.createDataSource(dataSource: self.frcDataSource)
Once the data source is created we will have an AnyDataSource typed object that can be used in place of a DataSourceProtocol type.
Basically what we’ve done is create wrappers for two types