iOS BlocksKit初体验

2019-08-11  本文已影响0人  邓布利多教授

前段时间,一个偶然的机会,让我遇到了BlocksKitRAC(ReactiveCocoa),说来惭愧,做iOS开发这么久,到目前为止还有很多东西不熟悉,偶然遇到一个“新词”完全一脸懵逼,根本就不知道是啥玩意。所以现在有时间就会到处逛,看到一个就会记录一个,当前时间看不完的,我会记录起来,找时间慢慢的看。在此还要问一下大家学习iOS相关知识的都有哪些好的网站或好的去处,麻烦评论留下,谢过了……

说到BlocksKitRAC,之前网上查了一下。我是先看的RAC,因为第一眼我看成了ARC,我说这东西不是自动管理内存的吗,后面再仔细看,原来是RAC,是ReactiveCocoa的缩写。目前我查到的资料都说RAC配合MVVM框架使用,体验感超级棒,简单看了下,说了很多什么信号之类的东西,因为在我开发的过程中,也从来没用过这个RAC,所以一时半会看的我头昏眼花,然后就暂时放着不看了。转眼看看BlocksKit,看到最后我发现这两东西好像就是一回事似的,因为都是各种Block,搞的现在看啥东西都觉得像是需要加上一对{}才行。

还有一个奇怪的现象,文章看完的时候我是习惯性要看一下各位的评论的,因为评论里面的内容往往会很精彩,有时候会发现一些对我来说比较的东西,这个时候我就发现很多类似的说法,总结一下就是无论是BlocksKit还是RAC,都会和很多库产生冲突,早以放弃使用这两个框架。因为我没在项目里面用过BlocksKitRAC,朋友们又没具体说会和哪些库产生冲突,所以我更不清楚到底是怎么回事了。当然了,看过的文章大部分都是15、16、17年的,有一些是18年的,特意筛选了近一年内关于BlocksKitRAC的文章,很明显文章数少了很多,难道真的早就没人在用了吗?

不管怎么说,既然被我看到了,至少我也得看看源码吧。首先着手看的是BlocksKit,还看了一些以前的文章,大致了解了它的用法,接下来,我会简单的说一下我对BlocksKit的理解和简单的使用。

BlocksKit理解

看源码可以看出各种Block,对我们经常用的一些控件做了很多的扩展,也算是对一些常用的方法封装了一层,调用的时候代码量减少了很多,直观感觉清晰了很多。还有对一些不具备某些特性功能的控件增加了方法,比如说UIView添加点击事件等等。

首先添加BlocksKit到你的TestProject,我是用CocoaPods来管理这些第三方框架的,不会使用CocoaPods的看这里

然后引入你用到的这个框架的头文件,我用到了三个,分别如下:

#import <BlocksKit/BlocksKit.h>
#import <BlocksKit/A2DynamicDelegate.h>
#import <BlocksKit/BlocksKit+UIKit.h>

UIView

UIView是我们经常用到的一个控件,UIView继承UIResponderUIResponder继承NSObject,这些大家查看API就知道了,我在这有点废话了。后面的一些控件也不再废话了,直接看test代码。

UIView *vBlock = [UIView new];
vBlock.backgroundColor = [UIColor orangeColor];
[self.view addSubview:vBlock];
[vBlock mas_makeConstraints:^(MASConstraintMaker *make) {
    make.size.mas_equalTo(CGSizeMake(200, 200));
    make.centerX.mas_equalTo(self.view.mas_centerX);
    make.centerY.mas_equalTo(self.view.mas_centerY);
}];

文档解释是这样说的,后面的文档说明代码不再粘贴,大家可以自行下载源码查看,源码下载地址

/** Adds a recognizer for one finger tapping once.
 
 @warning This method has an _additive_ effect. Do not call it multiple
 times to set-up or tear-down. The view will discard the gesture recognizer
 on release.

 @param block The handler for the tap recognizer
 @see whenDoubleTapped:
 @see whenTouches:tapped:handler:
 */
/*
给View添加点击事件
*/
[vBlock bk_whenTapped:^{
    NSLog(@"view点击");
}];

说明:我只是随便选了几个控件,并从每个控件的扩展方法里选了几个简单的方法试了试,没有对全部代码进行解读,大家有兴趣的可以自己去玩一玩。

UIButton

给Button添加事件的常规写法是先添加方法,然后再实现这个方法,代码如下:

/*
给Button添加事件
*/
[btnBlock addTarget:self action:@selector(buttonAction) forControlEvents:UIControlEventTouchUpInside];

/*
实现方法
*/
-(void)buttonAction{
    NSLog(@"buttonAction");
}

如果要传参数的话,代码如下:

/*
给Button添加事件
*/
[btnBlock addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];

/*
实现方法
*/
-(void)buttonAction:(UIButton *)sender{
    NSLog(@"buttonAction = %ld",sender.tag);
}

BlocksKit就为我们提供了这么一个精简的代码段,如下:

[btnBlock bk_addEventHandler:^(id sender) {
        NSLog(@"按钮点击");
    } forControlEvents:UIControlEventTouchUpInside];

如果同样是需要传参数的呢?注意,这里需要自己手动把(id sender)改写成(UIButton *sender)代码如下:

[btnBlock bk_addEventHandler:^(UIButton *sender) {
        NSLog(@"按钮点击 = %ld",sender.tag);
    } forControlEvents:UIControlEventTouchUpInside];

NSDictionary

NSDictionary *dict = @{@"name":@"xiaohong",
                       @"age":@"18",
                       @"sex":@"女"};

遍历字典,查找字典中是否存在某些Key,并同时返回一个新的字典
调用方法为- (NSDictionary *)bk_select:(BOOL (^)(id key, id obj))block;

NSDictionary *dictEnd1 = [dict bk_select:^BOOL(id key, id obj) {
        
    NSLog(@"key = %@  obj = %@",key,obj);
    if ([key isEqualToString:@"name"] || [key isEqualToString:@"age"]) {
        return YES;
    }else{
        return NO;
    }
        
}];
NSLog(@"dictEnd1 = %@",dictEnd1);
打印结果 bk_select.png

根据以往的经验想一下,既然能把符合条件的键值对返回给我们,那肯定也能把不符合条件的键值对返回给我们吧?答案是肯定的,这样的方法同样也存在一个,它就是- (NSDictionary *)bk_reject:(BOOL (^)(id key, id obj))block;

NSDictionary *dictEnd2 = [dict bk_reject:^BOOL(id key, id obj) {

    NSLog(@"key = %@  obj = %@",key,obj);
    if ([key isEqualToString:@"name"] || [key isEqualToString:@"age"]) {
          return YES;
    }else{
          return NO;
    }

}];
NSLog(@"dictEnd2 = %@",dictEnd2);
打印结果 bk_reject.png

遍历字典,修改字典里每个Key对应的Value值,并同时返回一个新的字典,调用方法为- (NSDictionary *)bk_map:(id (^)(id key, id obj))block;

NSDictionary *dictEnd3 = [dict bk_map:^id(id key, id obj) {

      NSLog(@"key = %@  obj = %@",key,obj);
      return [NSString stringWithFormat:@"%@-edited",obj];

}];
NSLog(@"dictEnd3 = %@",dictEnd3);
打印结果 bk_map.png

NSArray

NSArray *stringArray = @[@"img5",@"img1",@"img2",@"img3",@"img4"];

遍历数组,调用方法为- (void)bk_each:(void (^)(id obj))block;

[stringArray bk_each:^(id obj) {
        NSLog(@"obj = %@",obj);
}];
打印结果 bk_each.png

遍历数组,查找目标元素,并返回,调用方法为- (id)bk_match:(BOOL (^)(id obj))block;

id some = [stringArray bk_match:^BOOL(id obj) {

        NSLog(@"obj = %@",obj);
        if ([obj isEqualToString:@"img3"]) {
            return YES;
        }
        return NO;

}];
NSLog(@"some = %@",some);
打印结果 bk_match.png

UITableView

通过看源码发现一个有趣的事,在A2DynamicDelegate.h里有这么一段说明,如下:

        // Create an alert view
        UIAlertView *alertView = [[UIAlertView alloc]
                                  initWithTitle:@"Hello World!"
                                  message:@"This alert's delegate is implemented using blocks. That's so cool!"
                                  delegate:nil
                                  cancelButtonTitle:@"Meh."
                                  otherButtonTitles:@"Woo!", nil];

        // Get the dynamic delegate
        A2DynamicDelegate *dd = alertView.bk_dynamicDelegate;

        // Implement -alertViewShouldEnableFirstOtherButton:
        [dd implementMethod:@selector(alertViewShouldEnableFirstOtherButton:) withBlock:^(UIAlertView *alertView) {
            NSLog(@"Message: %@", alertView.message);
            return YES;
        }];

        // Implement -alertView:willDismissWithButtonIndex:
        [dd implementMethod:@selector(alertView:willDismissWithButtonIndex:) withBlock:^(UIAlertView *alertView, NSInteger buttonIndex) {
            NSLog(@"You pushed button #%d (%@)", buttonIndex, [alertView buttonTitleAtIndex:buttonIndex]);
        }];

        // Set the delegate
        alertView.delegate = dd;

        [alertView show];

对这段代码的解释是这样的:A2DynamicDelegate implements a class's delegate, data source, or other delegated protocol by associating protocol methods with a block implementation.
翻译的大概意思就是:A2DynamicDelegate可以用Block的形式去实现类的委托、数据源或其他委托协议。

那么仿照这段代码,可以试试UITableView,因为UITableView既有DataSource,也有Delegate。首先,我用懒加载的方式创建TableView,用Masonry创建布局(这部分代码忽略),先把代码贴出来看下,代码如下:

-(UITableView *)tableView{
    
    if (!_tableView) {
        
        //初始化TableView
        _tableView = [[UITableView alloc]init];
        
#pragma mark - 设置Source
        //先把TableView的Source和BlockKit绑定
        A2DynamicDelegate *dataSource = _tableView.bk_dynamicDataSource;
        
        [dataSource implementMethod:@selector(tableView:numberOfRowsInSection:) withBlock:^NSInteger(UITableView *tableView, NSInteger section){
            return 10;
        }];
        
        [dataSource implementMethod:@selector(tableView:cellForRowAtIndexPath:) withBlock:^UITableViewCell *(UITableView *tableView, NSIndexPath *indexPath){
            
            static NSString *ident = @"Cell";
            UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ident];
            if (!cell) {
                cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ident];
            }
            
            cell.backgroundColor = [UIColor colorWithRed:arc4random_uniform(255)/255.0 green:arc4random_uniform(255)/255.0 blue:arc4random_uniform(255)/255.0 alpha:1];
            
            return cell;
            
        }];
        _tableView.dataSource = (id)dataSource;//必须有这句,把dataSource传回给TableView
        
#pragma mark - 设置Delegate
        //先把TableView的Delegate和BlockKit绑定
        A2DynamicDelegate *delegate = _tableView.bk_dynamicDelegate;
        
        [delegate implementMethod:@selector(tableView:heightForRowAtIndexPath:) withBlock:^CGFloat(UITableView *tableView, NSIndexPath *indexPath){
            return 80.f;
        }];
        
        [delegate implementMethod:@selector(tableView:didSelectRowAtIndexPath:) withBlock:^(UITableView *tableView, NSIndexPath *indexPath){
            NSLog(@"indexPath = %ld",indexPath.row);
        }];
        _tableView.delegate = (id)delegate;//必须有这句,把delegate传回给TableView
        
    }
    return _tableView;
    
}

好了,到此为止,就是我对BlocksKit所认识的一部分,写的不好,大神勿喷。至于这个框架会不会在以后的项目中使用,那还得看情况了……

全剧终

上一篇下一篇

猜你喜欢

热点阅读