做过几个项目以后,会用到比较深层次的block,开始学习阶段block都是通过mvc方式写,不会涉及到block时序问题,也不会有数据源绑定问题,因为controller不会被释放,你的数据都写在controller层。迈向大神的阶段就需要多用block封装view,数据只是在controller层获取,传到view层,在用block回调到controller层,也经常性的会用baseview去做数据传递。先来看一下,实现的效果图
可以看到tableview的cell中会有下架按钮,这个是一个block回调。一个高水平的ios开发者实现tableview不再直接通过tableview的代理方法来实现,而是自己将tableview的代理封装到baseview中。然后通过block回调来实现tableview的代理方法。下面通过代码来复现一下遇到的问题。
-(void)tableViewBuild
{
WS(weakSelf);
[self setCellInitCustomizer:^(UITableViewCell *cell, id cellData, NSInteger index){
ShopListCell * shopcell = [[ShopListCell alloc]initWithFrame:CGRectMake(0, 0, kScreenWidth, 209)];
ShopListBean * shoplistBean = cellData ;
shopcell.tapblock = ^(NSInteger tag) {
if (tag == 102) {
NSLog(@"点击下架");
[HomePageViewController requestXiajiaGoodsId:ShopListBean.goods_id withProduct_id:ShopListBean.product_id];
[weakSelf requestShopList];
}else if (tag == 103){
[HomePageViewController requestShareInfoWithGoodsId:bean.goods_id andProductId:bean.product_id];
}
};
[shopcell updateViewWithBean:shoplistBean];
[cell addCustomerView:shopcell];
}];
可以看到这个一个block回调,是初始化自定义cell,然后这个cell会有一个点击事件,也是一个block回调。那么问题来了。这个问题就是数据源绑定问题。block的难点之一。遇到的问题,就是点击下架,传递的商品id是上一个已经删除的商品。这就是block数据源绑定的问题。这是原来的写法。
解决问题,为什么出现了错乱的问题。因为tableviwe回调回来的数据源只是初始化的时候当你删除过一次,数据源就发生了对不上的问题。所以要确定cell的block传递过来的数据源就是当前cell 的。这样我们就需要对数据源多做一次处理,将代码修改如下。使用cell层传过来的数据模型;
shopcell.tapblock = ^(NSInteger tag,ShopListBean * bean) {
if (tag == 102) {
NSLog(@"点击下架");
[HomePageViewController requestXiajiaGoodsId:bean.goods_id withProduct_id:bean.product_id];
[weakSelf requestShopList];
}
在初始化cell回调中的update函数中,已经将对应的数据源传递过去,所以我们在cell层记录一下,然后放到cell的属性中。使用cell点击事件的时候 再将这个属性回传回来,这样就不会出现block的时序问题,已经数据源错乱问题
-(void)updateViewWithBean:(ShopListBean*)bean{
[_LeftIV sd_setImageWithURL:[NSURL URLWithString:bean.url]];
_goodsTitle.text = bean.name;
_bean = bean ;}
-(void)btnClick:(UIButton *)sender{
if (_tapblock) {
_tapblock(sender.tag,_bean);
}
}
理解了这个block的数据源绑定问题,不论多复杂也不会在遇到问题