美文网首页
Object-c block

Object-c block

作者: 哔哩哔哩智能喵 | 来源:发表于2017-01-09 13:13 被阅读22次

    block 在开发中的用途多种多样,一下是我遇到的block的常见用法

    • block 保存代码
    #import <Foundation/Foundation.h>
    
    @interface CellItem : NSObject
    
    @property (nonatomic, strong) NSString *title;
    
    // 保存每个cell做的事情
    @property (nonatomic, strong) void(^block)();
    
    + (instancetype)itemWithTitle:(NSString *)title;
    
    @end
    
    /************************/
    #import "CellItem.h"
    
    @implementation CellItem
    + (instancetype)itemWithTitle:(NSString *)title
    {
        CellItem *item = [[self alloc] init];
        
        item.title = title;
        
        return item;
    }
    @end
    
    /************************/
    #import "TableViewController.h"
    #import "CellItem.h"
    @interface TableViewController ()
    @property (nonatomic, strong) NSArray *items;
    @end
    
    @implementation TableViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        // 创建模型
        CellItem *item1 = [CellItem itemWithTitle:@"打电话"];
        item1.block = ^{
            NSLog(@"打电话");
        };
        CellItem *item2 = [CellItem itemWithTitle:@"发短信"];
        item2.block = ^{
            NSLog(@"发短信");
        };
        CellItem *item3 = [CellItem itemWithTitle:@"发邮件"];
        item3.block = ^{
            NSLog(@"发邮件");
        };
        _items = @[item1,item2,item3];
    }
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
        return _items.count;
    }
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        static NSString *ID = @"cell";
        
        // 1.从缓存池取
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
        
        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
        }
        
        CellItem *item = self.items[indexPath.row];
        cell.textLabel.text = item.title;
        
        return cell;
    }
    
    // 点击cell就会调用
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    {
        // 把要做的事情(代码)保存到模型
    
        CellItem *item = self.items[indexPath.row];
        
        if (item.block) {
            item.block();
        }
    }
    @end
    
    • block传值
    #import <UIKit/UIKit.h>
    @interface ModalViewController : UIViewController
    @property(nonatomic,strong)void(^block)(NSString *);
    @end
    
    /**********************/
    
    #import "ModalViewController.h"
    
    @interface ModalViewController ()
    
    @end
    
    @implementation ModalViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    }
    -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
        if (_block) {
            _block(@"123");
        }
        [self dismissViewControllerAnimated:YES completion:nil];
    }
    @end
    
    /**********************/
    #import "ViewController.h"
    #import "ModalViewController.h"
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
    }
    -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
        ModalViewController *modal = [[ModalViewController alloc]init];
        modal.view.backgroundColor = [UIColor blueColor];
        modal.block = ^(NSString *value){
            NSLog(@"value = %@",value);
        };
        
        [self presentViewController:modal animated:YES completion:nil];
    }
    
    @end
    
    
    • block内存管理
      • MRC:管理block
        • 只要Block引用外部局部变量,block放在栈里面.
      • block只能使用copy,不能使用retain,使用retain,block还是在栈里面
      • ARC:管理block
        • 只要block引用外部局部变量,block放在堆里面
      • block使用strong.最好不要使用copy
    • 只要block没有引用外部局部变量,block放在全局区
    • block造成的循环引用

    block中到底什么时候用weakSelf和strongSelf

    • 在看AFNetworking框架时我发现一种特别的block循环引用问题
    #import "ModalViewController.h"
    @interface ModalViewController ()
    @property (nonatomic, strong) void(^block)();
    @end
    
    @implementation ModalViewController
    
    - (void)dealloc
    {
        NSLog(@"ModalViewController销毁");
    }
    - (void)viewDidLoad {
        [super viewDidLoad];
        __weak typeof(self) weakSelf = self;
        _block = ^{
            __strong typeof(weakSelf) strongSelf = weakSelf;
            /**
             这种block两次引用第一次是把self修饰改成__weak,第二次的修饰改成了__strong又变成了强引用,而dispatch_after的block是由系统帮我们管理生命周期,所以两秒之后页面才会销毁
             */
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                NSLog(@"%@",strongSelf);
            });
        };
        _block();
    }
    
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
        [self dismissViewControllerAnimated:YES completion:nil];
    }
    @end
    
    • block变量传递
      • 如果block是局部变量,block是值传递
      • 如果是静态比那两,全局变量__block修饰的变量,block都是指针传递
    • block作为参数传递
    #import <Foundation/Foundation.h>
    @interface Manager : NSObject
    @property(nonatomic,assign)NSInteger result ;
    -(void)cacultor:(NSInteger(^)(NSInteger value))cacultorBlock;
    @end
    /*****************/
    #import "Manager.h"
    
    @implementation Manager
    -(void)cacultor:(NSInteger (^)(NSInteger))cacultorBlock
    {
        if (cacultorBlock) {
            _result = cacultorBlock(_result);
        }
    }
    @end
    /*****************/
    #import "ViewController.h"
    #import "Manager.h"
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // 把block当做参数,并不是马上就调用Block,什么时候调用,由方法内部决定
    // 什么时候需要把block当做参数去使用:做的事情由外界决定,但是什么时候做由内部决定.
        Manager *mgr = [[Manager alloc]init];
        [mgr cacultor:^NSInteger(NSInteger value) {
            value +=2;
            value *=2;
            NSLog(@"value = %ld",(long)value);
            return value;
        }];
    }
    @end
    
    
    • 在看masonry框架时发现一种block更加神奇的用法。
    #import <Foundation/Foundation.h>
    @interface Manager : NSObject
    @property(nonatomic,assign)NSInteger result ;
    -(Manager *(^)(NSInteger value))add;
    @end
    /***************/
    #import "Manager.h"
    @implementation Manager
    -(Manager *(^)(NSInteger))add
    {
        return ^(NSInteger value){
            _result += value;
            return self;
        };
    }
    @end
    /***************/
    #import "ViewController.h"
    #import "Manager.h"
    @interface ViewController ()
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        Manager *mgr = [[Manager alloc]init];
        mgr.add(5).add(5).add(3);
        NSLog(@"result = %ld",(long)mgr.result);
        self.test();
    }
    -(void(^)())test
    {
        return ^(){
            NSLog(@"block");
        };
        //    void(^block)() = ^{
        //     写法等同于上面
        //    };
    }
    
    @end
    

    相关文章

      网友评论

          本文标题:Object-c block

          本文链接:https://www.haomeiwen.com/subject/rsacbttx.html