標(biāo)簽: iOS 技術(shù)
接上篇,繼續(xù)block研究,這一篇講解實(shí)戰(zhàn)中的block反向傳值,一個(gè)非常實(shí)用的技術(shù)。
block反向傳值
- 前面我們已經(jīng)得知,block可以作為參數(shù)而進(jìn)行傳遞
- 也知道block是封裝了一段代碼塊,如同函數(shù)一樣,我們可以調(diào)用它,并用來(lái)傳遞一些信息,比如某個(gè)我們需要的參數(shù)值!
- 但block的經(jīng)典使用,還是其反向傳值的簡(jiǎn)單明了
先看代碼
#import "TCHomeViewController.h"
#import "TCHomeCell.h"
static NSString *const kTCHomeCellIdentifier = @"TCHomeCell";
@interface TCHomeViewController () <UITableViewDelegate, UITableViewDataSource>
@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, strong) NSMutableArray<NSString *> *titles;
@end
@implementation TCHomeViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor whiteColor];
self.titles = @[].mutableCopy;
[self setupUI];
[self setupData];
}
#pragma mark - UI
- (void)setupUI {
[self.view addSubview:self.tableView];
self.tableView.frame = self.view.bounds;
[self.tableView registerClass:[TCHomeCell class] forCellReuseIdentifier:kTCHomeCellIdentifier];
}
- (void)setupData {
NSArray *arr = @[@"我是誰(shuí)!",
@"我是人!??",
@"我是詩(shī)人!??",
@"我是大詩(shī)人!??",
@"我是偉大詩(shī)人!??"];
self.titles = [NSMutableArray arrayWithArray:arr];
}
#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.titles.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TCHomeCell *cell = [tableView dequeueReusableCellWithIdentifier:kTCHomeCellIdentifier forIndexPath:indexPath];
cell.title = self.titles[indexPath.row];
cell.homeCellBtnClickBlock = ^(BOOL isSelected) {
// 拿到isSelected值,作進(jìn)一步操作
if (isSelected) {
NSLog(@"下載中");
}
};
return cell;
}
#pragma mark - getter
- (UITableView *)tableView {
if (!_tableView) {
_tableView = [[UITableView alloc] init];
_tableView.delegate = self;
_tableView.dataSource = self;
_tableView.rowHeight = 60.0f;
}
return _tableView;
}
@end
#import <UIKit/UIKit.h>
typedef void(^TCHomeCellBtnClickBlock)(BOOL isSeleted);
@interface TCHomeCell : UITableViewCell
@property (nonatomic, copy) TCHomeCellBtnClickBlock homeCellBtnClickBlock;
@property (nonatomic, strong) NSString *title;
@end
#import "TCHomeCell.h"
@interface TCHomeCell ()
/// 標(biāo)題標(biāo)簽
@property (nonatomic, strong) UILabel *titleLabel;
/// 下載按鈕
@property (nonatomic, strong) UIButton *downloadBtn;
@end
@implementation TCHomeCell
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
[self setupUI];
}
return self;
}
#pragma mark - UI
- (void)setupUI {
[self.contentView addSubview:self.titleLabel];
[self.contentView addSubview:self.downloadBtn];
CGFloat width = self.frame.size.width;
CGFloat height = self.frame.size.height;
self.titleLabel.frame = CGRectMake(10, 10, width * 0.5, height * 0.8);
self.downloadBtn.frame = CGRectMake(width, 10, 80, height * 0.8);
}
#pragma mark - action
- (void)clickDownloadBtn:(UIButton *)btn {
BOOL selected = !btn.selected;
if (self.homeCellBtnClickBlock) {
self.homeCellBtnClickBlock(selected);
}
}
#pragma mark - setter
- (void)setTitle:(NSString *)title {
if ([_title isEqualToString:title]) {
return;
}
_title = title;
self.titleLabel.text = _title;
}
#pragma mark - getter
- (UILabel *)titleLabel {
if (!_titleLabel) {
_titleLabel = [[UILabel alloc] init];
_titleLabel.font = [UIFont systemFontOfSize:17.0];
_titleLabel.textColor = [UIColor blackColor];
[_titleLabel sizeToFit];
}
return _titleLabel;
}
- (UIButton *)downloadBtn {
if (!_downloadBtn) {
_downloadBtn = [UIButton buttonWithType:UIButtonTypeCustom];
_downloadBtn.frame = CGRectMake(0, 0, 100, 40);
_downloadBtn.backgroundColor = [UIColor darkGrayColor];
[_downloadBtn setTitle:@"download" forState:UIControlStateNormal];
[_downloadBtn setTitleColor:[UIColor orangeColor] forState:UIControlStateNormal];
[_downloadBtn addTarget:self action:@selector(clickDownloadBtn:) forControlEvents:UIControlEventTouchUpInside];
}
return _downloadBtn;
}
@end
說(shuō)明
- 第一段代碼是控制器里面的代碼,處理業(yè)務(wù)邏輯
- 第二段代碼是視圖cell的.h代碼,提供了兩個(gè)API
- 第三段代碼是視圖cell的.m代碼,是處理視圖和數(shù)據(jù)展示的
解釋
- 在cell的.h文件中,定義了一個(gè)block屬性,并定義了一個(gè)形參
BOOL isSelected,那么這個(gè)形參就是我們需要傳遞的值,即傳給控制器的進(jìn)行業(yè)務(wù)處理的值- 在.m文件中,通過(guò)按鈕的點(diǎn)擊事件
-clickDownloadBtn:來(lái)進(jìn)行block回調(diào),即self.homeCellBtnClickBlock(selected);- 那么我們需要用這個(gè)block來(lái)傳值,即
selected,利用這個(gè)BOOL值來(lái)做進(jìn)一步操作,每一個(gè)cell都是不同的,而且我們也只能通過(guò)cell對(duì)象來(lái)訪問block屬性,故而block塊寫在了cell的初始化中,當(dāng)我們點(diǎn)擊cell的按鈕,就會(huì)有相應(yīng)的操作,在代碼中的block塊是NSLog代碼,通過(guò)這些打印我們知道按鈕的變化,而這些邏輯就恰好交由控制器處理,正好也體現(xiàn)了MVC的設(shè)計(jì)思想
程序運(yùn)行展示

界面展示
點(diǎn)擊事件
點(diǎn)擊download按鈕,就會(huì)在控制臺(tái)上看到打印輸出
2016-12-06 11:11:08.177 TCMyBlockDemo[8816:2632787] -[ViewController clickBtn:]
2016-12-06 11:11:16.283 TCMyBlockDemo[8816:2632787] 下載中
由此說(shuō)明,傳值成功!
寫在最后
反向傳值是block最實(shí)用的技術(shù),當(dāng)然也可以用代理來(lái)傳值,但定義代理、實(shí)現(xiàn)代理,是一個(gè)比較繁復(fù)的過(guò)程,而且代碼也不精簡(jiǎn)。
對(duì)代理熟悉的朋友可以試試,相信這樣的實(shí)戰(zhàn)在項(xiàng)目中經(jīng)常用到,如果你用膩了代理,那么不妨試試block
那么,關(guān)于block實(shí)戰(zhàn)的大致內(nèi)容也就差不多結(jié)束了,至于block在堆棧是怎么存在的,有很多文章可以搜到。我個(gè)人的block系列文章,都是在實(shí)戰(zhàn)中用到的,相信可以為一部分迷茫的朋友有所幫助,當(dāng)然如果真幫到了你,那么我這辛苦也就值了。
最后,感謝點(diǎn)贊,歡迎批評(píng)指正,歡迎轉(zhuǎn)載,完結(jié)!