解决Block相互引用的问题

   为了更好的看出Block的相互引用,本文采用自定义Button演示 。可以看出四个对象的相互引用。

先看控制器的.m文件吧,

#import "ViewController.h"
#import "MyButton.h"
#import "SecendControllerViewController.h"
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
//MyButton的类在下面    
MyButton *btn = [MyButton buttonWithType:UIButtonTypeCustom];
    btn.frame = CGRectMake(100, 100, 100, 100);
    
    btn.backgroundColor = [UIColor orangeColor];
    
    [self.view addSubview:btn];
    //按钮的点击时间用Block实现
    [btn addtapBlock:^(UIButton *btn){
    
        NSLog(@"dianji le ");
        
    }];
    
}
//touches方法,当手指开始触摸时调用
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//导航控制器,这个不用说了,大家都知道
    SecendControllerViewController *VC = [[SecendControllerViewController alloc]init];
    
    [self.navigationController pushViewController:VC animated:YES];
    
    
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end
//第二个控制器 .h文件
<pre name="code" class="objc">#import <UIKit/UIKit.h>

@interface SecendControllerViewController : UIViewController

{
    NSInteger _index;
}

@end

//.m文件<pre name="code" class="objc">//
//  SecendControllerViewController.m
//  ARC-09-11Block 解决相互引用
//
//  Created by imac on 15/9/11.
//  Copyright (c) 2015年 imac. All rights reserved.
//

#import "SecendControllerViewController.h"
#import "MyButton.h"
@interface SecendControllerViewController ()

@end

@implementation SecendControllerViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    self.view.backgroundColor = [UIColor lightGrayColor];
    
    MyButton *btn = [MyButton buttonWithType:UIButtonTypeCustom];
    btn.frame = CGRectMake(100, 100, 100, 100);
    
    btn.backgroundColor = [UIColor brownColor];
    
    [self.view addSubview:btn];
    
    _index = 90;
   
    // 循环引用:self -> self.view - > btn -> block - self
    //block copy全局变量时,为了保证其不被销毁,将持有_index属性的对象也copy了
    //在MRC中如何解决:__block SecendControllerViewController *this = self;
    
    
    //在ARC环境中的解决方法
    __weak SecendControllerViewController *weark = self;
    
    
    [btn addtapBlock:^(UIButton *btn){
    
        //无法直接用weark指向_index;
        __strong SecendControllerViewController *strongthis = weark;
        
       strongthis->_index = 20;
        
        NSLog(@"%ld",strongthis->_index);
        
        //此时才能把 button 销毁
        
        //如果还是直接调用对象方法,也会造成内存泄漏
        //[self text];(错误)
        //因此 此时还应该用
        [weark text];
        
    }];
    
    
}

- (void)text{

    NSLog(@"----");
}

 
//myButton.h
<pre name="code" class="objc">#import <UIKit/UIKit.h>
//定义一个Blcok类型
typedef void (^MyBlock)(UIButton *);

@interface MyButton : UIButton

@property (nonatomic, copy)MyBlock block;
//模仿按钮自定义方法
- (void)addtapBlock:(MyBlock)block;

@end
//.m
<pre name="code" class="objc">#import "MyButton.h"

@implementation MyButton

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

- (void)addtapBlock:(MyBlock)block
{

    //如果在这里直接进行回调,程序一运行完就会调用
    //block(self);(错误)
    
    //为了保证block能够在合适的时机调用,且为了保证是同一个block
    //(如果是在MRC环境中,要用self.block = block)
    _block = block;
    
    [self addTarget:self action:@selector(btnAction:) forControlEvents:UIControlEventTouchUpInside];
    
    
}
- (void)btnAction:(UIButton *)btn
{
     //block的回调,
    _block(self);
}
@end


 


 


 

#import "ViewController.h"
#import "MyButton.h"
#import "SecendControllerViewController.h"
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
//MyButton的类在下面    
MyButton *btn = [MyButton buttonWithType:UIButtonTypeCustom];
    btn.frame = CGRectMake(100, 100, 100, 100);
    
    btn.backgroundColor = [UIColor orangeColor];
    
    [self.view addSubview:btn];
    //按钮的点击时间用Block实现
    [btn addtapBlock:^(UIButton *btn){
    
        NSLog(@"dianji le ");
        
    }];
    
}
//touches方法,当手指开始触摸时调用
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//导航控制器,这个不用说了,大家都知道
    SecendControllerViewController *VC = [[SecendControllerViewController alloc]init];
    
    [self.navigationController pushViewController:VC animated:YES];
    
    
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end
//第二个控制器 .h文件
<pre name="code" class="objc">#import <UIKit/UIKit.h>

@interface SecendControllerViewController : UIViewController

{
    NSInteger _index;
}

@end

//.m文件<pre name="code" class="objc">//
//  SecendControllerViewController.m
//  ARC-09-11Block 解决相互引用
//
//  Created by imac on 15/9/11.
//  Copyright (c) 2015年 imac. All rights reserved.
//

#import "SecendControllerViewController.h"
#import "MyButton.h"
@interface SecendControllerViewController ()

@end

@implementation SecendControllerViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    self.view.backgroundColor = [UIColor lightGrayColor];
    
    MyButton *btn = [MyButton buttonWithType:UIButtonTypeCustom];
    btn.frame = CGRectMake(100, 100, 100, 100);
    
    btn.backgroundColor = [UIColor brownColor];
    
    [self.view addSubview:btn];
    
    _index = 90;
   
    // 循环引用:self -> self.view - > btn -> block - self
    //block copy全局变量时,为了保证其不被销毁,将持有_index属性的对象也copy了
    //在MRC中如何解决:__block SecendControllerViewController *this = self;
    
    
    //在ARC环境中的解决方法
    __weak SecendControllerViewController *weark = self;
    
    
    [btn addtapBlock:^(UIButton *btn){
    
        //无法直接用weark指向_index;
        __strong SecendControllerViewController *strongthis = weark;
        
       strongthis->_index = 20;
        
        NSLog(@"%ld",strongthis->_index);
        
        //此时才能把 button 销毁
        
        //如果还是直接调用对象方法,也会造成内存泄漏
        //[self text];(错误)
        //因此 此时还应该用
        [weark text];
        
    }];
    
    
}

- (void)text{

    NSLog(@"----");
}

 
//myButton.h
<pre name="code" class="objc">#import <UIKit/UIKit.h>
//定义一个Blcok类型
typedef void (^MyBlock)(UIButton *);

@interface MyButton : UIButton

@property (nonatomic, copy)MyBlock block;
//模仿按钮自定义方法
- (void)addtapBlock:(MyBlock)block;

@end
//.m
<pre name="code" class="objc">#import "MyButton.h"

@implementation MyButton

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

- (void)addtapBlock:(MyBlock)block
{

    //如果在这里直接进行回调,程序一运行完就会调用
    //block(self);(错误)
    
    //传参
    //(如果是在MRC环境中,要用self.block = block)
    _block = block;
    
    [self addTarget:self action:@selector(btnAction:) forControlEvents:UIControlEventTouchUpInside];
    
    
}
- (void)btnAction:(UIButton *)btn
{
     //block的回调,
    _block(self);
}
@end


 


 


 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值