標籤:
1.簡介
在之前的文章[New learn]講解Objective-c的block知識中介紹了block的相關知識。本章中我們將以一個實際例子來簡單介紹一下block如何代替代理。
2.原有通過代理實現方式回顧
在[How to] 使用Xib來建立view中我們介紹了如何通過xib來自訂table的footview,如何通過代理的方式來通知controller去載入更多資料。
相應的代碼:https://github.com/xufeng79x/tableView_groupbuy_test
1.在上述項目中我們在XFLoadMoreView.h標頭檔中聲明了一個協議
@protocol XFLoadMoreViewDelegate <NSObject>/** * 當按鈕點擊後通知代理實現對象 * * @param loadMoreView 觸發者本身 */@optional-(void) loadMoreViewDidClickedToLoadBtn:(XFLoadMoreView *) loadMoreView;@end
2.在自訂的XFLoadMoreView中聲明了代理屬性:
代理屬性,指向顯示了此代理的對象,防止循環參考需要使用weak屬性參數@property (nonatomic,weak) id<XFLoadMoreViewDelegate> delegate;
3.在controller中去實現了此協議,並在建立XFLoadMoreView執行個體的時候將其代理屬性值設定為當前controller,以此來進行通知調用。
@interface XFGoodsShowsViewController () <UITableViewDataSource, XFLoadMoreViewDelegate>。。。。。。。。。。。// 載入按鈕按下後通知到此對象調用此方法-(void) loadMoreViewDidClickedToLoadBtn:(XFLoadMoreView *) loadMoreView{ // 這裡我們類比增加一個團購的資訊,插入到列表的最好一行 XFGoodModel *model = [[XFGoodModel alloc] init]; model.image = @"image.jpg"; model.name = @"new food"; model.price = 123; model.soldNum = 321; // 將次資訊插入到表資料來源中 [self.goodsList addObject:model]; // 需要將此資料塞入table的最後一行 NSIndexPath *indexPath = [NSIndexPath indexPathForItem:self.goodsList.count - 1 inSection:0]; [self.goodsTableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationTop]; // 載入完畢後將table滾到新加入的行那裡,也就是最後一條 [self.goodsTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];}。。。。。。。
3.使用block特性來替代代理特性機制
我們可以不使用通過協議以代理的方式去做,我們可以通過block來處理:
具體方法為:
1.在XFLoadMoreView.h檔案中聲明block屬性,用於接收來自目標的回調block
// 定義通知回調@property(nonatomic,strong) void (^notifyLoadBlock)(XFLoadMoreView *);
2. 將XFLoadMoreView.m類初始化方法中增加block參數
// 利用block來進行通知回調的初始化方法+(instancetype) loadMoreViewWithNotifyBlock:(void (^)(XFLoadMoreView *)) notifyLoadBlock{ // 直接從xib中載入view XFLoadMoreView *loadView = [[[NSBundle mainBundle] loadNibNamed:@"XFLoadButton" owner:nil options:nil] lastObject]; // 美化按鈕,將按鈕的四個角圓潤化 loadView.loadMoreBtnView.layer.cornerRadius = 5; loadView.loadMoreBtnView.layer.masksToBounds = YES; // 設定載入更多回調block loadView.notifyLoadBlock = notifyLoadBlock; return loadView;}
3.在controller處初始化XFLoadMoreView的時候將具體block實現傳入:
// 載入tableView的footview XFLoadMoreView *loadMoreView = [XFLoadMoreView loadMoreViewWithNotifyBlock:^(XFLoadMoreView * view){ [self loadMoreViewDidClickedToLoadBtn:view]; }];
這裡重複利用了原有協議方式中的方法。
4.當自訂XFLoadMoreView中發生載入事件的時候去通知controller載入資料:
/** * 點擊載入更多按鈕後觸發 */- (IBAction)loadMoreClick { // 將botton隱藏讓後將載入樣式呈現 self.loadMoreBtnView.hidden = YES; self.loadMoreIngView.hidden = NO; // 使用此方法能夠達到順延強制效果 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2.0 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ self.loadMoreBtnView.hidden = NO; self.loadMoreIngView.hidden = YES; // 向代理髮送資訊,由於是代理定義中設定的是可選方法,所以發送資訊之前需要檢查是否實現了此方法// if ([self.delegate respondsToSelector:@selector(loadMoreViewDidClickedToLoadBtn:)])// {// [self.delegate loadMoreViewDidClickedToLoadBtn:self];// } // 使用回調進行載入通知 if (nil != self.notifyLoadBlock) { self.notifyLoadBlock(self); } });
4.總結
在本文中我們將一個原本通過代理的方式實現的功能通過block方式實現。
那麼何時應該採用代理何時應該採用block呢?
我們可以參考如下文章:http://stackoverflow.com/questions/26791548/objc-memory-usage-of-delegate-vs-block
本章代碼:https://github.com/xufeng79x/BlockDemo
[New learn]講解Objective-c的block知識-實踐