objc.io does a great job of explaining how to slim down your view controllers but what Swift has done is make this process even easier.
The core of the process is to shift the boiler plate of creating datasources/delegates out to an object which owns that flow and inject that datasource into each of the relevant view controllers
Swift functions are full class objects which can be flung around the place with great ease. Its true that Objective-C allows you to store and copy blocks to much the same effect but it never sat well and always felt a bit funky especially with the need to draw out the block signatures and the need to do weak self reference dances .
In Swift this changes and feels very natural.
So where in Objective-C you might do this.
typedef void (^FreakyBlock)(UICollectionViewCell *cellToConfigure, DataThing *thing);
@class MagicDivorcedCollectionViewDatasource <UICollectionViewDataSource>
@end
@implementation MagicDivorcedCollectionViewDatasource
@property (copy) FreakyBlock cellConfigurationBlock
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@”Cell” forIndexPath:(NSIndexPath *)indexPath];
//common setup
//pass the cell to the block for view specific decoration
if(cellConfigurationBlock) {
cellConfigurationBlock(cell)
}
}
and then within the view controller
-(void)setupDatasource {
//here might be where you inject a managed object context at init
self.collectionDatasource = [[MagicDivorcedCollectionViewDatasource alloc] init];
__block typeof(self) blockself = self;
//view specific routine for decorating generic cell
self.collectionDatasource.cellConfigurationBlock = ^(UICollectionViewCell *cellTo Configure, DataThing *thing) {
cell.label = thing.name;
cell.otherLabel = thing.subname;
cell.backgroundColor = [blockself backgroundColorForThing:thing];
}
}
two files and so much boiler plate later, so freaking bored now.This bunch of code burns down to this in Swift
class MagicDivorcedCollectionViewDatasource: UICollectionViewDataSource {
var cellConfigurator:((UICollectionViewCell,DataThing)->Void)?
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath:indexPath) as UICollectionViewCell;
let dataObject = self.dataObjectForIndexPath(indexPath) as DataThing
cellConfigurator?.(cell,dataObject)
return cell
}
and in your view controller
func configureCell(cell:UICollectionViewCell,thing:DataThing) {
cell.label.text = thing.name
cell.otherLabel.text = thing.subname
cell.backgroundColor = self.backgroundColorForThing(thing)
}
func setupDatasource() {
collectionDatasource = MagicDivorcedCollectionViewDatasource()
//simply pass the function to the class. its an object.
collectionDatasource.cellConfigurator = configureCell
}
It feels a lot less clanky and more amenable to use.


No comments:
Post a Comment