Block 与 循环引用

作者: json_jie | 来源:发表于2015-03-26 14:30 被阅读1546次

    貌似 。。。。。理解有错误
    。。。。。。。。。。了

    前言:闲着太久了,最近补血,此刻来兴致写点东西
    (1)说明一下内存位置
    栈:上的内存 又编译器来管理
    堆:上的内存又操作者来管理,is you or me
    (2)block这个东西。。。随便乱用问题很大,从心里不建议胡乱用,当你没有彻底理解的时候,真心建议不要为了代码的优雅而使用,老老实实用代理来的好,自己用不好的话,多考虑考虑队友的感受,还是不要用的好。难点:就是内存管理,出现循环引用的问题。
    (3)即使你用Instruments检测到循环引用引起的内存泄露的问题,可是他是不靠谱的(我貌似用着都是靠谱,据听说好多人说不靠谱,我就这样写啦,吓吓人,多点注意的啊)。

    优点 : Block可以访问上下文的外部变量的值。换句话说,Block不仅 实现函数的功能,还能携带函数的执行环境。
    说明:
    (1)局部自动变量,在Block中readOnly。这样理解吧:Block定义时copy变量的值(相当于一块副本)。保存变量的瞬间值,在Block中作为常量使用,所以即使变量的值在Block外改变,也不影响他在Block中的值。
    (2)STATIC修饰符变量(全局和 局部) 和全局变量
    STATIC修饰符变量(全局和 局部) 和全局变量 在内存中的地址是固定的,Block在读取该变量值的时候是直接从其所在内存读出,获取到的是最新值,而不是在定义时copy的常量.
    (3)__block修饰的变量称作Block变量 == 等效于全局变量、或静态变量。

    呜呜呜呜呜。。。。 又特么三分钟热度特么的不想写了 直接来代码自己体会去吧。。。来简单的犀利的看代码吧

    (1)
    //
    // ViewController.h
    // xunHuan
    //
    // Created by jie on 15/3/26.
    // Copyright (c) 2015年 jie. All rights reserved.
    //

    import <UIKit/UIKit.h>

    @interface ViewController : UIViewController

    @end

    //
    // ViewController.m
    // xunHuan
    //
    // Created by jie on 15/3/26.
    // Copyright (c) 2015年 jie. All rights reserved.
    //

    import "ViewController.h"

    import "OneViewController.h"

    @interface ViewController ()

    @end

    @implementation ViewController

    • (void)viewDidLoad {
      [super viewDidLoad];

      self.view.backgroundColor = [UIColor orangeColor];
      self.title = @"View";
      UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
      btn.frame = CGRectMake(100, 100, 120, 40);
      [btn setTitle:@"Press Action" forState:UIControlStateNormal];
      [btn addTarget:self action:@selector(pressAction) forControlEvents:UIControlEventTouchUpInside];
      [self.view addSubview:btn];

    [OneViewController transferClassMethod:^(int a, NSString *s) {
        NSLog(@"ViewController = %d   %@",a,s);
        self.view.backgroundColor = [UIColor brownColor];
    }];
    

    }
    -(void)pressAction
    {
    OneViewController *one = [[OneViewController alloc] init];
    [self.navigationController pushViewController:one animated:YES];
    }
    -(void)dealloc
    {
    NSLog(@"dealloc ViewController");
    }
    @end

    (2)
    //
    // OneViewController.h
    // xunHuan
    //
    // Created by jie on 15/3/26.
    // Copyright (c) 2015年 jie. All rights reserved.
    //

    import <UIKit/UIKit.h>

    typedef void(^myBlock) (int a,NSString *s);
    @interface OneViewController : UIViewController
    +(void)transferClassMethod:(myBlock)block;
    -(void)exampleClassMethod:(myBlock)block;
    @end

    //
    // OneViewController.m
    // xunHuan
    //
    // Created by jie on 15/3/26.
    // Copyright (c) 2015年 jie. All rights reserved.
    //

    import "OneViewController.h"

    import "TwoViewController.h"

    @interface OneViewController ()

    @end

    @implementation OneViewController

    • (void)viewDidLoad {
      [super viewDidLoad];
      self.title = @"One";
      self.view.backgroundColor = [UIColor redColor];
      UIButton *bt = [UIButton buttonWithType:UIButtonTypeCustom];
      bt.frame = CGRectMake(100, 200, 120, 40);
      [bt setTitle:@"Preess One" forState:UIControlStateNormal];
      [bt addTarget:self action:@selector(ppppp) forControlEvents:UIControlEventTouchUpInside];
      [self.view addSubview:bt];
      }
      -(void)ppppp
      {
      TwoViewController *two = [[TwoViewController alloc] init];
      [self.navigationController pushViewController:two animated:YES];
      }
      +(void)transferClassMethod:(myBlock)block
      {
      block(100,@"zhaojie");
      }
      -(void)dealloc
      {
      NSLog(@"dealloc OneViewController");
      }

    -(void)exampleClassMethod:(myBlock)block
    {
    block(99,@"exampleMethod");
    }

    @end

    (3)
    //
    // TwoViewController.h
    // xunHuan
    //
    // Created by jie on 15/3/26.
    // Copyright (c) 2015年 jie. All rights reserved.
    //

    import <UIKit/UIKit.h>

    @interface TwoViewController : UIViewController
    @property(nonatomic,retain)NSString *propertyString;
    @end

    //
    // TwoViewController.m
    // xunHuan
    //
    // Created by jie on 15/3/26.
    // Copyright (c) 2015年 jie. All rights reserved.
    //

    import "TwoViewController.h"

    import "OneViewController.h"

    import "BlockButton.h"

    @interface TwoViewController ()
    {
    NSString *blockString;
    }
    @end

    @implementation TwoViewController

    • (void)viewDidLoad {
      [super viewDidLoad];
      self.title = @"Two";
      self.view.backgroundColor = [UIColor blueColor];
      blockString = @"blcokString";
      NSLog(@"blockString %@",blockString);

      self.propertyString = @"proString";
      NSLog(@"propertyString %@",self.propertyString);

    pragma mark 不会引起循环引用

    // (1)类方法一定不会   不会引起循环引用
    [OneViewController transferClassMethod:^(int a, NSString *s) {
        NSLog(@"ViewController = %d   %@",a,s);
        self.view.backgroundColor = [UIColor cyanColor];
        
        blockString = @"changBlockString";
        NSLog(@"change      %@",blockString);
        self.propertyString = @"ChangeproString";
        NSLog(@"ChangeproString      %@",self.propertyString);
    }];
    

    pragma mark

    //  (2)实例方法         self都没有持有OneViewController控制器本来就算不是闭环  不会引起循环引用啦
    OneViewController *one = [[OneViewController alloc] init];
    [one exampleClassMethod:^(int a, NSString *s) {
        NSLog(@"example  %d     %@",a,s);
        blockString = @"blockString";
        NSLog(@"blockString ===  %@",blockString);
        self.view.backgroundColor = [UIColor yellowColor];
        self.propertyString = @"example     ChangeproString";
        NSLog(@"example     self.propertyString    %@",self.propertyString);
    
    }];
    

    pragma mark ------- - 存在会引起的

    NSString *pargma = @"pargma";
    __block NSString *partString = @"partString";                      
    __block NSString *replaceString = blockString;// 全局的     =====      /*有问题*/
    __weak TwoViewController *controller = self;
    
    BlockButton *btn = [BlockButton buttonWithType:UIButtonTypeRoundedRect];
    btn.frame = CGRectMake(100, 100, 100, 100);
    btn.backgroundColor = [UIColor brownColor];
    [btn setTitle:@"Press Me" forState:UIControlStateNormal];
    btn.buttonBlock = ^(){
    

    pragma 9

        NSLog(@"partString   %@",pargma);       // 使用的局部变量   编译到block环境中  不会引起循环引用
    

    pragma 10

    // __block NSString *partString = @"partString"; // partString block变量 可以改变 不会引起循环引用
    partString = @"change partString"; // 局部变量
    NSLog(@"partString %@",partString);

    pragma mark 8

        // 会引起循环引用
    

    // self.view.backgroundColor = [UIColor cyanColor];
    // 解决办法
    controller.view.backgroundColor = [UIColor cyanColor];

    pragma mark 6

        // 会引起循环引用
    

    // self.propertyString = @"weak propertyString";
    // 解决办法
    controller.propertyString = @"weak propertyString";

    pragma mark 7

        // 会引起循环引用
    

    // NSLog(@" %@",self.propertyString);
    // 解决办法
    NSLog(@" %@",controller.propertyString);
    //

    pragma 4

        // 会引起循环引用
    

    // blockString = @"hallo blockString";
    // 解决办法
    //__block NSString *replaceString = blockString;// 全局的
    replaceString = @"hallo blockString";

    pragma 5

        // 会引起循环引用
    

    // NSLog(@"%@",blockString);
    // 解决办法
    //__block NSString *replaceString = blockString;// 全局的
    NSLog(@"%@",replaceString);

    pragma 3

        // 引起循环引用
    

    // self.propertyString = @"example ChangeproString";
    //解决办法
    controller.propertyString = @"example ChangeproString";
    NSLog(@"self.propertyStringself.propertyString %@",controller.propertyString);

    pragma 2

        // 引起循环引用
    

    // NSLog(@"self.propertyStringself.propertyString %@",self.propertyString);
    //解决办法
    NSLog(@"self.propertyStringself.propertyString %@",controller.propertyString);

    pragma 1

        // 引起循环引用
    

    // self.view.backgroundColor = [UIColor redColor];
    //解决办法
    controller.view.backgroundColor = [UIColor redColor];

    };
    [self.view addSubview:btn];  // 此时当前控制器持有 btn  如果出现btn持有当前控制器时。。。可能引起循环引用的情况
    

    }
    -(void)dealloc
    {
    NSLog(@"dealloc TwoViewController");
    }

    @end

    (4)

    //
    // BlockButton.h
    // blockButton
    //
    // Created by jie on 15/3/26.
    // Copyright (c) 2015年 jie. All rights reserved.
    //

    import <UIKit/UIKit.h>

    @class BlockButton;
    typedef void(^myButtonBlock) ();
    @interface BlockButton : UIButton
    @property(nonatomic,copy)myButtonBlock buttonBlock;

    @end

    //
    // BlockButton.m
    // blockButton
    //
    // Created by jie on 15/3/26.
    // Copyright (c) 2015年 jie. All rights reserved.
    //

    import "BlockButton.h"

    @implementation BlockButton
    @synthesize buttonBlock;

    • (id)initWithFrame:(CGRect)frame
      {
      self = [super initWithFrame:frame];
      if (self) {
      [self addTarget:self action:@selector(press) forControlEvents:UIControlEventTouchUpInside];
      }
      return self;
      }
      -(void)press
      {
      self.buttonBlock();
      }
      /*
      // Only override drawRect: if you perform custom drawing.
      // An empty implementation adversely affects performance during animation.
    • (void)drawRect:(CGRect)rect
      {
      // Drawing code
      }
      */

    @end

    // 补充一句 block 可以理解成一种类型 一种对象类型
    // Block就是OC的对象

    哎哎哎哎哎哎哎 不是写博客的料啊 可不容易想写一次。。。。。。。。。写这个逼样的

    最后这里边留下了 一个 bug
    NSString *pargma = @"pargma";
    __block NSString *partString = @"partString";
    __block NSString *replaceString = blockString;// 全局的 ?
    多想想吧
    提示:__block 重写该自动变量也不会改变原先的截取的自动变量 ===== 反之亦然

    那天补上。。。。。。 给说明白了 __block

    相关文章

      网友评论

      • 派大星的博客:直接粘代码,阅读行很差啊,
      • 爱上我们的微笑:兄弟你这个排版真心抠脚,写文章既然要写,就一定要写好。
      • 溪枫狼:辛苦了,整理这么多,“类方法一定不会循环引用”这句话有点过于绝对了,类方法不返回实例对象或者self不强引用返回的实例对象才能避免循环引用。。。今天也被block坑了把,想跟你请教下,我现在有个奇葩的想法,有个类方法带有block并且返回实际对象b,b强引用了block(成员属性),现在想在b对象的block里面随便用A类的self,但是Self强引用了b,b是self的成员属性,会多次调用block,而不是只调用一次,并且不在A类里面用weakSelf,只想在B里面做点手脚避免循环引用又能多次调用。不知道你有没有思路?

      本文标题:Block 与 循环引用

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