Block专辑:

Block讲解一

MRC-block与ARC-block

Block详解一(底层分析)

今天讲述Block的最后一篇,后两篇仅仅是加深1,2篇的理解,废话少说,开始讲解!

  • __block细节
  • __block内存管理
  • 循环引用问题

一:__block细节

大家可能会遇到下面的问题,block的内部想要修改外部的auto变量,但是编译器会报问题!如下

如果block内部想要修改外部的auto变量,可以在int age 前面加入static修饰词,变为静态局部变量(会一直存在内存中,反而不好),以及可以将int age代码移植到函数外面变为全局变量! 除此之外还有没有其他的做法了呢,显然是有的,通过__block修饰,如下:

发现__block修改外面变量是可以达到目的的! 小结论

  1. __block可以用于解决block内部无法修饰auto变量值的问题
  2. __block不能修饰全局变量、静态变量(static)
  3. 编译器会将__block变量包装成一个对象

通过命令

xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m

生成main.cpp代码查看原理

上面提到可以将int main函数的代码简化一下,简化成如下

首先拿到forwarding指针然后再拿到age的值

二:__block的内存管理

1. 当block在栈上时,并不会对__block变量产生强引用;

2. 当block被copy到堆时

  1. 会调用block内部的copy函数
  2. copy函数内部调用_Block_object_assign函数
  3. _Block_object_assign函数会对__block变量形成强引用(retain)

3.当block从堆中移除时

  1. 会调用block内部的dispose函数
  2. dispose函数内部会调用_Block_object_dispose函数
  3. _Block_object_dispose函数会自动释放引用的__block变量(release)

拓展:__block的_forwarding指针

栈上block的forwarding指针指向堆上的block,而堆上block的forwarding指针指向自己本身的指针。

三:循环引用

关于block循环引用的基本概念,专辑block已经讲解,本篇讲述核心内容

1. 解决循环引用问题-ARC

(1) 用__weak、__unsafe_unretained解决

下面用例子来巩固下

int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *person = [[Person alloc]init];
__weak Person *weakPerson = person;
person.block = ^{
NSLog(@"age is %d", weakPerson.age);
};
}
NSLog(@"");
return ;
} #import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
typedef void(^ZXYBlock)(void);
@interface Person : NSObject
@property(nonatomic,copy)ZXYBlock block;
@property(assign, nonatomic)int age;
@end #import "Person.h"
@implementation Person
-(void)dealloc {
NSLog(@"%s", __func__);
}
@end

__weak方式解决循环引用问题

__unsafe_unretained方式解决循环引用问题

__weak,__unsafe_unretained都可以解决循环引用,有什么区别呢?

结论

相同点:__weak和__unsafe_unretained都不会产生强引用

不同点:__weak指向对象销毁时,会自动让指针置为nil;__unsafe_unretained不安全,指向对象销毁时,指针存储地址         不变,如果再次访问可能会造成野指针

(2) 用__block方式解决

下面来探究一下为什么__block可以解决循环引用?看下编译成的c++代码

以前结合__block 对象变量以及__block自动变量可知:c++包含了三个对象,如下

上面的三种关系如下,调用person = nil就是为了打断其中一个循环引用链条,但是必须要调用block()

2. 解决循环引用问题-MRC

MRC下,首先要在编译器上设置为MRC环境。Build Settings->Automatic Reference Counting设为No

(1) 用__unsafe_unretained解决

因为MRC下不存在弱指针,所以不存在__weak修饰解决循环引用

(2) 用__block解决

总结

上面是block最后一篇的讲解,关于block总共有四篇博客,应该可以讲解完所有关于block的内容,应该会大大增加大家对block底层的理解,如果觉得有意义有所帮助,欢迎点赞和关注,本人会及时更新博客!!!

Block详解二(底层分析)的更多相关文章

  1. Block详解一(底层分析)

    本篇博客不再讲述Block的基本定义使用,最近而是看了很多的block博客讲述的太乱太杂,所以抽出时间整理下block的相关底层知识,在讲述之前,提出几个问题,如果都可以回答出来以及知道原理,大神绕过 ...

  2. 关于syslog日志功能详解 事件日志分析、EventLog Analyzer

    关于syslog日志功能详解 事件日志分析.EventLog Analyzer 一.日志管理 保障网络安全 Windows系统日志分析 Syslog日志分析 应用程序日志分析 Windows终端服务器 ...

  3. PopUpWindow使用详解(二)——进阶及答疑

      相关文章:1.<PopUpWindow使用详解(一)——基本使用>2.<PopUpWindow使用详解(二)——进阶及答疑> 上篇为大家基本讲述了有关PopupWindow ...

  4. Android View 的绘制流程之 Layout 和 Draw 过程详解 (二)

    View 的绘制系列文章: Android View 的绘制流程之 Measure 过程详解 (一) Android View 绘制流程之 DecorView 与 ViewRootImpl 在上一篇  ...

  5. LinkedList详解-源码分析

    LinkedList详解-源码分析 LinkedList是List接口的第二个具体的实现类,第一个是ArrayList,前面一篇文章已经总结过了,下面我们来结合源码,学习LinkedList. 基于双 ...

  6. .NET DLL 保护措施详解(二)关于性能的测试

    先说结果: 加了缓存的结果与C#原生代码差异不大了 我对三种方式进行了测试: 第一种,每次调用均动态编译 第二种,缓存编译好的对象 第三种,直接调用原生C#代码 .net dll保护系列 ------ ...

  7. iOS开发——Block详解

    iOS开发--Block详解 1. Block是什么 代码块 匿名函数 闭包--能够读取其他函数内部变量的函数 函数变量 实现基于指针和函数指针 实现回调的机制 Block是一个非常有特色的语法,它可 ...

  8. Android 布局学习之——Layout(布局)详解二(常见布局和布局参数)

    [Android布局学习系列]   1.Android 布局学习之——Layout(布局)详解一   2.Android 布局学习之——Layout(布局)详解二(常见布局和布局参数)   3.And ...

  9. logback -- 配置详解 -- 二 -- <appender>

    附: logback.xml实例 logback -- 配置详解 -- 一 -- <configuration>及子节点 logback -- 配置详解 -- 二 -- <appen ...

随机推荐

  1. sitemesh 使用方法

    一.简介 SiteMesh是一个网页布局和修饰的框架,利用它可以将网页的内容和页面结构分离,以达到页面结构共享的目的. 它能通过创建一个包装对象,也就是装饰来包裹的对象.尽管它是由Java语言来实现的 ...

  2. 由生到死10个月!做App中的“二”有多难

    十月,原本是怀胎过程的喜悦时光,但这段个时光,如今却是绝大多数App从生到死的所有时间.在App市场表面形式一片大好,彻底主宰我们生活.工作.娱乐的当下,绝大多数用户只是在App海洋中只取一瓢饮,其他 ...

  3. TCP\IP协议簇-分层模型

    OSI 模型   数据单元 层 功能 主机层 Data(数据) 7. 应用层 网络进程到应用程序. 6. 表示层 数据表示形式,加密和解密,把机器相关的数据转换成独立于机器的数据. 5. 会话层 主机 ...

  4. 将js进行到底:node学习9

    node.js数据库篇--Mongoose ODM 介绍mongoose 几乎所有的语言都有原生数据库连接驱动,这个我们上一回已经了解了,比如java的jdbc,mysql-connector,但是实 ...

  5. 关于sql拼接的知识点 where1=1

    String sql="select * from tab_route where 1 = 1 "; 这样不会报错,而且可以根据情况,再去拼接sql 可以使用if(){}else{ ...

  6. 【转载】[基础知识]【网络编程】TCP/IP

    转自http://mc.dfrobot.com.cn/forum.php?mod=viewthread&tid=27043 [基础知识][网络编程]TCP/IP iooops  胖友们楼主我又 ...

  7. 来自ebay内部的「软件测试」学习资料,覆盖GUI、API自动化、代码级测试及性能测试等,Python等,拿走不谢!...

    在软件测试领域从业蛮久了,常有人会问我: 刚入测试一年,很迷茫,觉得没啥好做的-- 测试在公司真的不受重视,我是不是去转型做开发会更好?  资深的测试架构师的发展路径是怎么样的?我平时该怎么学习? 我 ...

  8. 新财报再次巨亏 HTC还能活到2017吗?

    HTC还能活到2017吗?" title="新财报再次巨亏 HTC还能活到2017吗?"> 当下智能手机行业虽然竞争惨烈,但也称得上是精彩纷呈:性能.外形不断进化, ...

  9. Design Patterns in Android

    对日常在 Android 中实用设计模式进行一下梳理和总结,文中参考了一些网站和大佬的博客,如 MichaelX(xiong_it) .菜鸟教程.四月葡萄.IAM四十二等,在这里注明下~另外强烈推荐图 ...

  10. CSS过渡、动画及变形的基本属性与运用

    [逆战班] 动画可以让一个元素具有动态的效果,这个过程是使元素从一种样式变成另一个样式的过程.我们可以通过设置关键帧的方法来控制动画在某个时间节点的运动方式.通常设置多个节点来实现复杂的动画效果.0% ...