I am tasked with designing an application framework that will allow each implementation to customize parts of the user interface. One such example would be that the implementation (let's call it client from now on) can define the collection view cells to return for a particular screen. The framework is simply responsible for vending the appropriate objects to make building an App much easier since we will be building several similar looking instances.
My current approach to the framework has been to design a Coordination Controller that is responsible for all presentation and dismissal events throughout the App. The default Coordination Controller vends out all the default view controllers inside the framework that all perform their relevant tasks without necessarily providing configured UI. For instance: one controller will show a collection view with template cells and nothing special. The benefit of this design is that it removes the coupling between controllers and also allows for a client to override the default coordinator and return an entirely new view controller for a specific task.
The problem I'm having is how should I design this framework to allow a client to add their own custom UI into the App.
Approach One
Make the framework require a view factory and let this view factory be responsible for vending out all the relevant views. Thus, in the App Delegate we might enforce that the client create a CollectionViewCellFactory for instance and the interface defines all the cells that any conforming class will need to supply. I inherited a code base with this design and moved away from it as it was far too abstract and customizable. It came with tons of factories for every aspect of the App and this added days onto the setup time of every App.
Approach Two
Each view controller specifies subclassing hooks or setup API that will allow for these custom UI classes to be defined at run time (Similar to how UISplitViewController allows callers to setup the controllers using the viewControllers property). To do this each client will simply subclass the base Coordination Controller and in each controllers presentation; set the appropriate values onto the controller so that it achieves the desired UI. Something like
viewController.registerReusableCellsBlock = ^(UICollectionView *collectionView){
//perform custom registration
}
viewController.cellDequeueBlock = ^UICollectionViewCell<SomeProtocol> *(UICollectionView *collectionView,NSIndexPath *indexPath){
//dequeue custom cells
}
Currently, I separate the data source for a view into a separate object to promote reusability and prevent ViewController bloat. This makes subclassing the view controller to supply the interface of the cells a little harder but not impossible.
Approach 3
Perhaps its a bad idea to attempt to design a framework and anticipate its usage. Maybe the best option is to allow for subclassing with maximum control, even if the setup cost is relatively high. Then, once I've built it for several clients I might notice the patterns that emerge and begin optimization along the route.
I understand how I might make it customizable internal to the framework, what I'm struggling with is how to best define an interface that defines potential customization points of the framework by the client.
TL;DR
The most complicated part of the interface deals with a Collection View nested inside Collection View Cells. This allows for horizontal paging and vertical scrolling of cells. This is achieved by having one data source that manages the horizontal cells and configures each cell's collection view with a new data source.
How would one design an interface that allows all these cells to be customizable?