block巢狀的資料繫結問題,block時序問題
做過幾個專案以後,會用到比較深層次的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的資料來源繫結問題,不論多複雜也不會在遇到問題