zoukankan      html  css  js  c++  java
  • block底层实现原理

    1、关于block的循环引用:

    block属性,一般用copy修饰;

    1.1.如果没有对block进行copy操作,block就存储于栈空间

    1.2.如果对block进行copy操作,block就存储于堆空间---强引用

    1.3.如果block存储于栈空间,不会对block内部所用到的对象产生强引用

    1.4.如果block存储于堆空间,就会对block内部所用到的对象产生强引用

    注意1:由于使用了copy修饰,如果block中调用了block属性的对象,就会造成循环引用

      为了避免循环引用,需要对对象进行若引用修饰:

    1 ICKPerson *p = [[ICKPerson alloc] init];
    2 // 1、修饰方法1
    3     //    __unsafe_unretained typeof(p) weakP = p;
    4 // 2、修饰方法2
    5     __block typeof(p) weakP = p;
    6     p.testBlock = ^{
    7         [weakP run];
    8     };

    2、关于block中变量的值:

    2.1  如果变量没有通过__block修饰,那么block中的变量本质是值捕获,在创建block的同时,是将变量的值传入到block,无论什么时候调用,变量的值就是最初传进去的值

    1  int age = 10;
    2  void (^block)() = ^{ // 值捕获
    3    NSLog(@"age=%d", age);// 打印是10;
    4  };
    5  age = 20;
    6  block();

    2.2  如果变量通过__block修饰,那么block中的变量实际传递的是变量的地址,在创建block的同时,是将变量的地址传入到block,在调用block的时候,其变量的值是当时变量的值(通过地址(指针)获取到)。

    1 __block int age = 12  void (^block)() = ^{ // 值捕获
    3         NSLog(@"age=%d", age);// 打印是20;
    4   };
    5     age = 20;
    6     block();

    3、关于block的内部实现:

            创建block的时候,内部是创建了对应的函数;

            在调用block的时候,是调用了之前封装的函数。

    4、关于block的应用:

     4.1.如何定义block

     1  1// inline
     2      // blockName:block变量名
     3      // 返回值类型(^变量名)(返回值类型)
     4      <#returnType#>(^blockName)(<#parameterTypes#>) = ^(<#parameters#>) {
     5      <#statements#>
     6      };
     7 void(^block)() = ^(){
     8         NSLog(@"block");
     9     };
    10  2// name:Block类型别名
    11 typedef void(^MyBlock)()
    12  MyBlock myBlock = ^(){
    13   };

       4.2、调用block

    1  block();
    2  myBlock();

      4.3、实战练习:

        // 4.通讯录Block使用:

        // 点击保存,通知联系人刷新表格,用代理

        // block:小弟 代理:打电话

        // block:先把刷新表格的代码保存起来

        // 等用户点击了保存按钮的时候,调用Block

    4.3.1、在头文件中(向其他文件中传递数据的文件)定义一个block:是否带参数,根据需求确定

    1 @class ICKAddViewController,ICKContact;
    2 typedef void(^ICKAddViewControllerBlock)(ICKContact *contact);
    3 @interface ICKAddViewController : UIViewController
    4 @property (nonatomic, strong) ICKAddViewControllerBlock contactBlock;
    5 @end

    4.3.2、在获取数据后,跳转页面之前,调用block,将数据传递过去

    1 - (IBAction)addcontact {
    2     ICKContact *contact = [ICKContact contactWithName:self.nameFiled.text andPhone:self.phoneFiled.text];
    3     // 调用block
    4     if (self.contactBlock) {
    5         self.contactBlock(contact);
    6     }
    7     [self.navigationController popViewControllerAnimated:YES];
    8 }

    4.3.3、在获取(保存、利用)数据的文件中(拿到获取数据的对象的时候)调用其block属性,保存block代码段(实现特定功能的代码)

     1 // 跳转控制器时数据传递
     2 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
     3     ICKAddViewController *addVc = segue.destinationViewController;
     4     // 声明block
     5     addVc.contactBlock = ^(ICKContact *contact){
     6         [self.contacts addObject:contact];
     7 
     8         // 存储数据
     9         NSString *cache = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];
    10         NSString *path = [cache stringByAppendingString:@"contacts.data"];
    11         [NSKeyedArchiver archiveRootObject:self.contacts toFile:path];
    12         [self.tableView reloadData];
    13     };
    14 }

     

  • 相关阅读:
    Spring 事务不回滚
    Druid详细配置信息
    Servlet和JSP规范及版本对应关系
    CDN(内容分发网络)技术原理
    开发者需要了解的WebKit
    浏览器的渲染原理简介
    在浏览器中输入Google.com并且按下回车之后发生了什么?
    为什么说DOM操作很慢
    亿级Web系统搭建——单机到分布式集群
    linux下用rinetd做端口转发
  • 原文地址:https://www.cnblogs.com/jfckliving/p/4775024.html
Copyright © 2011-2022 走看看