ios开发block的使用,ios开发 block

iOS开发面试拿offer攻略之block篇

Block 是将函数及其执行上下文封装起来的对象。 比如:

成都创新互联专业为企业提供武鸣网站建设、武鸣做网站、武鸣网站设计、武鸣网站制作等企业网站建设、网页设计与制作、武鸣企业网站模板建站服务,10多年武鸣做网站经验,不只是建网站,更提供有价值的思路和整体网络服务。

通过 clang -rewrite-objc WYTest.m 命令编译该 .m 文件,发现该 block 被编译成这个形式:

其中 WYTest 是文件名, blockTest 是方法名,这些可以忽略。其中 WYTest blockTest_block_impl_0 结构体为

--block_impl 结构体为

block 内部有 isa 指针,所以说其本质也是 OC 对象

block 内部则为:

所以说 Block 是将函数及其执行上下文封装起来的对象

既然 block 内部封装了函数,那么它同样也有参数和返回值。

如果你正在跳槽或者正准备跳槽不妨动动小手,添加一下咱们的交流群1012951431来获取一份详细的大厂面试资料为你的跳槽多添一份保障。

这里的输出是 6 而不是 2,原因就是对局部变量 num 的截获是值截获。同样,在 block 里如果修改变量 num ,也是无效的,甚至编译器会报错。

打印为 1,2,3

局部对象变量也是一样,截获的是值,而不是指针,在外部将其置为 nil ,对 block 没有影响,而该对象调用方法会影响

输出为 2,意味着 num = 1 这里的修改 num 值是有效的,即是指针截获。同样,在 block 里去修改变量 m ,也是有效的。

编译后

( impl.isa = _NSConcreteStackBlock ;这里注意到这一句,即说明该 block 是栈 block )

可以看到局部变量被编译成值形式,而静态变量被编成指针形式,全局变量并未截获。而 --block 修饰的变量也是以指针形式截获的,并且生成了一个新的结构体对象:

该对象有个属性: num5 ,即我们用 --block 修饰的变量。这里 --forwarding 是指向自身的(栈 block )。

一般情况下,如果我们要对 block 截获的局部变量进行赋值操作需添加 --block 修饰符,而对全局变量,静态变量是不需要添加 --block 修饰符的。

另外, block 里访问 self 或成员变量都会去截获 self 。

分为全局 Block(_NSConcreteGlobalBlock) 、栈 Block(_NSConcreteStackBlock) 、堆

Block(_NSConcreteMallocBlock) 三种形式

其中栈 Block 存储在栈 (stack) 区,堆 Block 存储在堆 (heap) 区,全局 Block 存储在已初始化数据 (.data) 区

输出:

比如:

输出:

日常开发常用于这种情况:

比如堆 1中的全局进行 copy 操作,即赋值:

输出:

仍是全局 block

而对 2中的栈 block 进行赋值操作:

输出:

对栈 blockcopy 之后,并不代表着栈 block 就消失了,左边的 mallock 是堆 block ,右边被 copy 的仍是栈 block 比如:

输出:

即如果对栈 Block 进行 cop ,将会 copy 到堆区,对堆 Block 进行 copy ,将会增加引用计数,对全局 Block 进行 copy ,因为是已经初始化的,所以什么也不做。

另外, --block 变量在 copy 时,由于 --forwarding 的存在,栈上的 --forwarding 指针会指向堆上的-- forwarding 变量,而堆上的 --forwarding 指针指向其自身,所以,如果对 --block 的修改,实际上是在修改堆上的 --block 变量。

即 --forwarding 指针存在的意义就是,无论在任何内存位置,都可以顺利地访问同一个 --block 变量 。

另外由于 block 捕获的 --block 修饰的变量会去持有变量,那么如果用 --block 修饰 self ,且 self 持有

block ,并且 block 内部使用到 --block 修饰的 self 时,就会造成多循环引用,即 self 持有 block , block 持有 --block 变量,而 --block 变量持有 self ,造成内存泄漏。

比如:

如果要解决这种循环引用,可以主动断开 --block 变量对 self 的持有,即在 block 内部使用完 weakself 后, 将其置为 nil ,但这种方式有个问题,如果 block 一直不被调用,那么循环引用将一直存在。

所以,我们最好还是用 --weak 来修饰 self

以上就是 block 篇的面试题合集了,感谢观看~!

iOS block深入理解

   在平时的开发中,对于block,只是知道主要用于数据回调上,对于其内部实现方式,以及一些使用时的注意事项,还不是很了解。在网上找个一些关于block的文章,做了一个简单的整理。希望对于想学习研究block的同学有帮助。另外,非常感谢这些文章的作者,感谢你们把自己的知识经验分享出来。

首先是一篇唐巧的文章,对于唐巧,作为iOS开发者应该不陌生。

谈Objective-C block的实现

下边这篇文章是block的学习使用

OS开发-由浅至深学习block

下边这篇文章是在唐巧的文章中摘出来的,写的也很详尽。作者也引用了很多其他优秀的文章,可以作为学习参考。

对Objective-C中Block的追探

下边这篇文章也对block的原理做了很详细的介绍,

Objective-C中的Block

再次感谢以上开发者的分享,如果大家有其他优秀的文章,欢迎留言分享,一起进步学习。

iOS中block的使用详解

然而若定义一个block属性,并在block的实现中做如下操作:

此时当调用ModalViewController的dismiss方法的时候不会调用dealloc方法中的打印语句,说明ModalViewController没有被真正的销毁。因为ModalViewController强引用一个block属性,block会对内部的强指针self进行一次强引用。所以造成循环引用

如果这样呢?

这样呢?

这样呢?

iOS __block 到底做了啥

如果想在block内部修改从外部捕获的auto变量的值,可以在该auto变量定义的时候,加上关键字__block

__block只可以用来作用于auto变量,它的目的就是为了能够让auto变量能够在block内部内修改。而全局变量和static变量本来就可以从block内部进行修改,因此__block对它们来说没有意义,所以__block被规定只能用于修饰auto变量

我们把main.m 文件 改成main.cpp文件看下block到底是什么。

为了比较,我特意加了一个int b作为对比。

基本类型的auto变量被block捕获的时候,就是通过值拷贝的形式把值赋给block内部相对应的基本类型变量。而例子里的__block int a = 10,我们可以看到在底层,系统是把int a包装到了一个叫__Block_byref_a_0的对象里面。

看下__block_byref_a_0的对象里有啥:

这样能看出来,外面使用__block 修饰的int a 在__block_byref_a_0对象里,就是最后的int a 这个结构体里的int a 也就是我们在block里需要调用的a。

1、在block外部 使用__block修饰变量。

2、在block内部使用被修饰的变量时,会创建一个__Block_byref_xx_0 *_xx对象。(此处的xx为变量名,下同)

3、被创建的对象,会生成__Block_byref_xx_0 *__forwarding;//指向自身类型对象的指针

4、最后__forwarding这个指针指向最新的值,然后再指回__Block_byref_xx_0 *_xx

5、最终当我们打印的时候,如果变量被__block修饰了,会被内部修改。

ios 开发中 怎么使用block 代替代理方法

声明一个无返回值的block

typedef void(^onSearch)(NSString *searchText); ////////onSearch 就是这个block的函数指针

2.在控制器中头文件.h中定义block,分两步:

1定义成属性

@property (nonatomic)  onSearch searchBlock;

2定义一个block的setter方法

-(void)setSearchBlock:(void(^)(NSString *searchText)) block;

3.在控制器的实现文件.m中来实现

-(void)setSearchBlock:(void(^)(NSString *searchText)) block {

if (block) {

self.searchBlock = block;

}

}

4.在控制器中使用block实现回调. 当点击search按钮时,将search的文本传递给订阅者

-(void)searchHandler:(id)sender {

if (self.searchBlock) {

self.searchBlock(@"your search keyword")

}

}

5.在订阅者中,接收过来的参数,并做其它操作

YourVC  *vc = [YourVC new];

[vc setSearchBlock:^(NSString *searchText) {

NSLog(@"get search keyword")       

}]

如何在ios中使用block

声明和使用Block:

Apple文档中介绍了如何将一个Block声明为变量,并将其作为一个函数使用:

int (^oneFrom)(int) = ^(int anInt) {

return anInt - 1;

};

// 创建了一个内联块^(int anInt)... ,其函数体和结果被传到了另外一个名为OneFrom的Block。

printf("1 from 10 is %d", oneFrom(10));

// 打印出: "1 from 10 is 9"

// 这个block函数(distanceTraveled)传入3个float型参数,返回float值。

float (^distanceTraveled) (float, float, float) =

^(float startingSpeed, float acceleration, float time) {

float distance = (startingSpeed * time) + (0.5 * acceleration * time * time);

return distance;

};

也可以传入一个Block作为一个参数,而不要以如上的方式声明,这样就可以在需要将block作为参数的时候以内联代码的方式简单地实现。

NSArray *anArray = [NSArray arrayWithObjects: @"cat", @"dog",nil];

sortFunction(anArray, ^(string *a string *b){

if ( a == @"cat") return TRUE; });


文章标题:ios开发block的使用,ios开发 block
当前网址:http://ybzwz.com/article/phgeoc.html