OC Block 循环引用

一、什么是Block

1、Block是iOS中一种比较特殊的数据类型:

2、既然是数据类型,那么就可以通过该数据类型声明变量,并保存数据.Block数据类型不是用来保存int、double、NSString等数据,而是用来保存一段代码的。既然有变量可以保存一段代码,那么也就意味着可以把一段代码作为参数传递了。

3、Block是苹果官方特别推荐使用的数据类型,应用场景比较广泛。

   1)动画

   2)多线程

   3)集合遍历

   4)网络请求回调

4、Block的作用

   1)用来保存某一段代码,可以再恰当的时候取出来调用

   2)类似于函数和方法

5、语法介绍 如何声明Block

   1)无参数,无返回值

   2)带一个参数,无返回值

  3)带两个参数,一个返回值

6、Block的主成员素跟函数类似

  1)返回值

  2)形式参数

  3)实际参数

7、Block的定义格式

返回值类型 (^block变量名)(形参列表)= ^(形参列表) {

 

};

没有参数可以写void,比如:int (^blockname)(viod);

8、调用Block保存的代码

block变量名(实参);

1)使用typedef定义block类型。定义好以后就可以像普通数据类型那样使用了:typedef返回值类型(^block类型名称)(形参列表);

二、使用注意

1)默认情况下,Block内部不能修改外面的局部变量

2)Block内部可以修改使⽤用__block修饰的局部变量(如果想修改请使⽤用__block 修饰)

3)Block调⽤用前注意判断是否为nil,否则可能会报错!

4)使⽤Xcode用inlineBlock⾃自动⽣生成block定义代码(辅助记忆)

5)block在ARC中和MRC中的用法有什么区别,需要注意什么

   不管是ARC和MRC,block都应该用copy操作来持有

   应用避免循环应用

   ARC: __weak、__unscafe_unretained

   MRC:__block

 

、三解决循环引用的方法,好废话不多说,上代码;

 

#import<UIKit/UIKit.h>

 


@interface ViewController : UIViewController


@end

 

 

 

#import "ViewController.h"
#import "NetWorkTools.h"

@interface ViewController ()
@property (nonatomic, strong) NetWorkTools *tools;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    //self.tools = [NetWorkTools alloc]init]  会造成循环引用
   
   
    //第三种解决方式
    //__unsafe_unretained  和 assgin关键字 效果一致
    //EXC_BAD_ACCESS 在MRC时代  最常见的错误  坏内存地址访问 野指针
    //当对象被系统回收时  它的内存地址 不会自动指向nil
    // __unsafe_unretained  是 iOS4.0推出
    self.tools = [[NetWorkTools alloc]init];
    __unsafe_unretained typeof (self) weakSelf = self;
    [self.tools loadData:^(NSString *html) {
        NSLog(@"%@ %@",html,weakSelf.view);
    }];
   
   
}

- (void)metmod2{
   
    //第二种解决方法
    //__weak 声明一个弱引用类型的自己  来解除
    //__weak 和 weak 当对象被系统收回时 它的内存地址 会自动指向 nil
    //__weak typeof(self) weakSelf = self;
    self.tools = [[NetWorkTools alloc]init];
    __weak typeof (self) weakSelf = self;
    [self.tools loadData:^(NSString *html) {
        NSLog(@"%@ %@",html,weakSelf.view);
    }];


}


//第一种解决方法
- (void) metmod1{
    //self.tools = [NetWorkTools alloc]init]  会造成循环引用
    NetWorkTools *tools = [[NetWorkTools alloc]init];
    [tools loadData:^(NSString *html) {
        NSLog(@"%@ %@",html,self.view);
        self.view.backgroundColor = [UIColor redColor];
    }];

}

//工作中会常见到这样的
- (void)metmod {
    __weak typeof(self) weakSelf = self;
    [self.tools loadData:^(NSString *html) {
        //用强引用对弱引用的对象 做一次'强'的操作
        __strong typeof(self) strongSelf = weakSelf;
        NSLog(@"%@%@",html,strongSelf.view);
        strongSelf.view.backgroundColor = [UIColor redColor];
    }];

}

- (void)dealloc {

    NSLog(@"view 88");
}

 

@end

 

 

 

—————下面是Tool类------------------

 

 

 

#import <Foundation/Foundation.h>

@interface NetWorkTools : NSObject

- (void) loadData:(void(^)(NSString *html))finisfedCallBack;

 

@end

 

 

 

#import "NetWorkTools.h"

@interface NetWorkTools ()

@property (nonatomic, copy) void(^finishedBlock)(NSString *);

@end

@implementation NetWorkTools

- (void)loadData:(void (^)(NSString *))finishedCallBack {

    //开始记录Block
    self.finishedBlock = finishedCallBack;
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
       
        //执行耗时操作
        [NSThread sleepForTimeInterval:3];
       
        NSLog(@"开始加载数据");
        dispatch_async(dispatch_get_main_queue(), ^{
            [self working];
        });
    });

}
- (void)working {

    //执行Block
    if (self.finishedBlock) {
        self.finishedBlock(@"<html>");
    }

}

- (void)dealloc {
    NSLog(@"Tools 挂了");
}

 

@end

 

 

 

 

有什么问题请大家提出,一起修改、学习; 

posted on 2016-03-29 10:38  陈肖坤  阅读(509)  评论(1编辑  收藏  举报

导航