为了更好的看出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