iOS开发-Block简介

Block简称闭包,实际上就是一个程序块,Block的名称类似于函数的入口地址,有自己的作用域范围,在作用域结束接受后被销毁(通常函数结束后),通常被分配在栈中(以便访问局部变量和提高性能),Block本身是一个objective-c 中的对象,适用于内存管理方法,我们可以使用Block来完成一些同步执行的程序片段,封装一些小型的工作和完成一项工作时的回调(callback)。Blocks 作为传统回调函数的一个实用的替代办法,有以下两个原因:

1.它们可以让你在调用的地方编写代码实现后面将要执行的操作。 因此 Blocks 通常作为框架方法的参数。

2.它们允许你访问局部变量。而不是需要使用一个你想要执行操作时集成所有上下文的信息的数据结构来进行回调,你可以直接简 单的访问局部变量。

1.Block的常用写法

1.声明一个block和它的实现

void (^my_block)(void)=^(void){

NSLog("my block");

}

my_block();

2.可以定义一个Block类型

typedef void(^my_block_type)(void)

my_block_type my_block = ^(void){

NSLog("my block");

}

2.Block对变量的访问

默认情况情况下block使用到的局部变量都会被复制,而不是保留.所以它无法改变局部变量的值.

如果在变量面前加上__block, 那么编译器不会复制变量, 而是去找变量的地址, 通过地址来访问变量, 实际上就是直接操作变量.

另外块是在栈上分配的, 所以一旦离开作用域, 就会释放, 因此如果你要把快用在别的地方, 必须要复制一份.

所以在属性定义一个快的时候需要使用copy:  @property (nonatomic, copy) void (^my_block_type)(void);

块是不能保留的, retain对块没有意义.

3.Block在底层实现就是一个结构体数据结构。

对应的结构体定义如下:

struct Block_descriptor {

unsigned long int reserved;

unsigned long int size;

void (*copy)(void *dst, void *src);

void (*dispose)(void *);

};

struct Block_layout {

void *isa;

int flags;

int reserved;

void (*invoke)(void *, ...);

struct Block_descriptor *descriptor;

/* Imported variables. */

};

通过该图,我们可以知道,一个block实例实际上由6部分构成:

1.isa指针,所有对象都有该指针,用于实现对象相关的功能。

2.flags,用于按bit位表示一些block的附加信息,本文后面介绍block copy的实现代码可以看到对该变量的使用。

3.reserved,保留变量。

4.invoke,函数指针,指向具体的block实现的函数调用地址。

5.descriptor, 表示该block的附加描述信息,主要是size大小,以及copy和dispose函数的指针。

6.variables,capture过来的变量,block能够访问它外部的局部变量,就是因为将这些变量(或变量的地址)复制到了结构体中。

4.ARC和非ARC中block的区别:

ARC下Block何时会从栈自动被复制到推, 以及__block和__weak的使用问题

由于Block是默认建立在栈上, 所以如果离开方法作用域, Block就会被丢弃, 在非ARC情况下, 我们要返回一个Block ,需要 [Block copy];

在ARC下, 以下几种情况, Block会自动被从栈复制到堆:

1.被执行copy方法

2.作为方法返回值

3.将Block赋值给附有__strong修饰符的id类型的类或者Blcok类型成员变量时

4.在方法名中含有usingBlock的Cocoa框架方法或者GDC的API中传递的时候.

对于非ARC下, 为了防止循环引用, 我们使用__block来修饰在Block中实用的对象:

__block id blockSelf=self;

self.blk=^{

NSLog(@"%@",blockSelf);  //在非ARC下对于栈上的_block对象, Block不会对其复制, 仅仅使用, 不会增加引用计数.

};

对于ARC下, 为了防止循环引用, 我们使用__weak来修饰在Block中实用的对象:

__weak id weakSelf=self;

self.blk=^{

NSLog(@"%@",weakSelf);

};

时间: 2024-09-29 18:26:46

iOS开发-Block简介的相关文章

IOS中 Block简介与用法(一)

?Block简介: Block的实际行为和Function很像,最大的差别是在可以存取同一个Scope的变量值.Block实体形式如下: ^(传入参数列){行为主体}; Block实体开头是"^",接着是由小括号所包起来的参数列(比如 int a, int b, int c),行为主体由大括号包起来,专有名字叫做block literal.行为主体可以用return回传值,类型会被compiler自动辨别.如果没有参数列要写成: ^(void). 例如下面的一个例子: [cpp] vi

iOS开发——Block引起循环引用的解决方案

内存问题始终是软件开发中的头等大事,iOS开发中也不例外,在面试中也是必问的问题.今天我们主要来讲讲Block中涉及的循环引用问题.当我们自己一开始写代码的时候,可能会大量在block中使用self,但是当看到别人优秀的代码的时候,发现别人常常不是用self,而使用weakSelf. 为什么呢?本文的示例代码上传至 https://github.com/chenyufeng1991/Block_WeakSelf . 首先我先来说说内存管理的原则: 1.默认使用strong,可选weak.stro

ios开发 Block(一) 代码块

一.什么是Blocks      Block是一个C级别的语法以及运行时的一个特性,和标准C中的函数(函数指针)类似,但是其运行需要编译器和运行时支持,从ios4.0开始就很好的支持Block. 二.在ios开发中,什么情况下使用Block      Block除了能够定义参数列表.返回类型外,还能够获取被定义时的词法范围内的状态(比如局部变量),并且在一定条件下(比如使用__block变量)能够修改这些状态.此外,这些可修改的状态在相同词法范围内的多个block之间是共享的,即便出了该词法范围

IOS开发block的使用

一个简单的block的定义: (void)(^myblock)()=^{ NSLog(@"------block输出----"); }; //调用blockmyblock(); 有参数和返回值的block (int)(^blockAdd)(int,int)=^(a,b){ return a+b; };//调用blockint sun = blockAdd(4,6); // 10 Block可以访问局部变量,但是默认情况下不能修该. 1如何传递一个block - (void)useWit

iOS开发-多线程-简介

iOS开发多线程篇—多线程简单介绍 一.进程和线程 1.什么是进程 进程是指在系统中正在运行的一个应用程序 每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内 比如同时打开QQ.Xcode,系统就会分别启动2个进程 通过“活动监视器”可以查看Mac系统中所开启的进程 2.什么是线程 1个进程要想执行任务,必须得有线程(每1个进程至少要有1条线程) 线程是进程的基本执行单元,一个进程(程序)的所有任务都在线程中执行 比如使用酷狗播放音乐.使用迅雷下载电影,都需要在线程中执行 3.线程

iOS开发-Block回调

关于Block之前有一篇文章已经写过一篇文章Object-C-代码块Block回顾,不过写的比较浅显,不能体现出Block在实际开发中的重要性,关于Block的基础知识,可以参考之前的博客.在实际开发中Block在回调过程中的是非常适合开发使用,不管是苹果的官方的接口还是一些第三方库的接口中都用到了Block回调.很多情况下Block和GCD一起使用,最常见的场景的就是App去后台取数据的过程中是需要时间,数据取成功之后我们才能更新UI页面,这就是最常见的回调的方式,也可以通过Notificat

iOS开发 Block的用法

一:在ios,blocks是对象,它封装了一段代码,这段代码可以在任何时候执行.Blocks可以作为函数参数或者函数的返回值,而其本身又可以带输入参数或返回值.它和传统的函数指针很类似,但是有区别:blocks是inline运行时使用的,并且它对局部变量是只读的;而在c语言中函数指针是在编译时就运行. int (^myBlock)(int ,int) = ^(int a, int b){return a ;}; 等号左边表示block的定义 ,右边表示 block的实现体 左边 int 表示 返

ios开发 Block(二) 实现委托

委托和block是IOS上实现回调的两种机制.Block基本可以代替委托的功能,而且实现起来比较简洁,比较推荐能用block的地方不要用委托. 实现效果如图 第一步,自定义CustomCell 1 #import <Foundation/Foundation.h> 2 3 @interface CustomCell : UITableViewCell 4 5 @property (strong, nonatomic) IBOutlet UILabel *labName; 6 @property

IOS开发—block对外部变量的内存管理

block对外部变量的内存管理 代码块在ios中通常用于回调,本文主要介绍block对外部变量的管理机制.我们知道如果要在block中使用block外面的变量,如果该变量是局部变量,就要先将其申明为__block类型.为什么呢?这就涉及到block对外部变量的内存管理. 一.基本数据类型 先看下面测试代码: //局部变量 - (void)localDataTest { int localData = 100; NSLog(@"localData --%p",&localData

iOS开发Block的介绍以及Block的循环引用问题

1:block的循环引用问题最主要记住两点: 如果[block内部]使用[外部声明的强引用]访问[对象A], 那么[block内部]会自动产生一个[强引用]指向[对象A] 如果[block内部]使用[外部声明的弱引用]访问[对象A], 那么[block内部]会自动产生一个[弱引用]指向[对象A] 2: #import "ViewController.h" #import "XMGPerson.h" @interface ViewController () @prop