前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >OC语言Block 续

OC语言Block 续

作者头像
用户1941540
发布于 2018-05-11 05:22:56
发布于 2018-05-11 05:22:56
57700
代码可运行
举报
文章被收录于专栏:ShaoYLShaoYL
运行总次数:0
代码可运行

OC语言 Block

转载:http://blog.csdn.net/weidfyr/article/details/48138167

1.Block对象中的变量行为

结论:

  1. 在block代码块内部可以访问定义的全局变量,局部变量,静态局部变量,但是访问局部静态变量时候是只读的并且局部变量和在代码块中访问到的不是同一个地址的变量,他们在数值上相等,互相似乎没什么联系。 因为代码块中使用到局部变量的时候,会将局部变量进行const类型的copy,所以在代码块中访问到的局部变量都是只读的;静态变量和全局变量都存放在静态区,在程序运行过程中都存在,他们可以在不同的代码块中共享,不同代码块中访问到的同一个全局变量,局部变量是同一块内存的数据;对于普通局部变量在代码块中只读,全局变量和静态局部变量在代码块中可以读写。
  2. 在块句法的主体中,除块句法内部的局部变量和形参之外,还包含块句法当前位置处可以访问的变量;这些变量中包含外部变量也包含块中可以访问的局部变量。
  3. 代码块中访问局部变量时候,局部变量会从栈内存被const类型的copy一份到堆内存中。
块对象和函数指针的定义使用功能都差不多,块对象的精髓之处就在于,在块对象中可以访问到上下文的变量,而函数指针不能。
2.块对象的实例和生命周期
  • 1)块句法也可以写在函数的外部,当写在函数外面时候,只是在静态数据区分配一块内存给块对象,这块区域在程序执行期间会一直存在。
  • 2)块句法写在函数内部的时候,块对象和变量的生命周期和普通局部变量一样,块对象的内存区域会在执行包含块对象的函数时保存在栈上;该块对象的生命周期就是函数运行期间。
  • 3)在现实的实现中,当函数内的块语法不包含自动变量的时候,就没必要进行复制值,所以块对象的内存区域也会被保存在静态数据区。
  • 4)block代码块被保存在堆或者静态区中,不会被保存在栈中,如下图可以说明这一点。
示例
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
- (void)function
{
    int i;
    int (^blocks[10])(); //定义一个块对象类型的数组
    for (i = 0; i < 10; i++) { //for循环给数组赋值
        blocks[i] = ^{ return i; };
    }
    for (i = 0; i < 10; i++) { //打印数组中的内容,就是每个数组存放的代码块的返回值
        NSLog(@"%d", blocks[i]());
    }
}
// 如上代码,在非ARC环境下运行结果是10个9,原因是虽然循环了十次,但是只有一个实体。
// 以上代码在ARC环境下是正确的,后面做说明。
3.块对象的复制
  • 函数内的块对象和局部变量的生命周期相同,都只是在函数的执行期间。但是在函数的方法调用参数中直接代入块对象也是块对象的一种非常常见的用法,这时候使用与函数调用关系或栈状态无关的块对象是非常必要的。
  • 有一个函数可以复制块对象到新的堆内存,通过使用该函数,即使是在函数内部定义的块对象也能独立于栈被持续的使用,此外还有一个函数可以释放不需要的块对象。

Block_copy( block )

  • 1.参数为栈上的块对象的时候,返回堆上的块对象。参数为堆上的块对象或者静态区的块对象,不进行复制,直接返回原对象,但是会增加参数块对象的引用计数。

Block_release( block )

  • 2.减少参数块对象的引用计数。当引用计数减到0时候,块对象被释放。
  • 3.在使用这些函数的时候,需要引入头文件Block.h .堆上的块对象使用引用计数的方式来管理。即使使用垃圾回收也必须成对出现。使用ARC时候可以不考虑这些,编译器会自动帮我们判断什么时候释放,什么时候保持。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 用法示例:
g = Block_copy(block);
Block_rlease(g);
4.指定特殊变量 __block
  • ARC下测试结果和总结:
  • 非ARC下测试结果和总结:

使用block时候注意事项:

使用注意事项:

  • 1)在块内改变外部变量的值时候,在外部变量前加__block,否则该值在block块内部是只读的。
  • 2)在引用某个实例变量或者所在控制器本身时候,在ARC下,要再前面加__weak如:__weak (typeof(self) weak self = self), 在mrc下用__block, 这样做是为了避免内存泄露和循环引用。
  • 3)在使用block前需要对block指针做判空处理,如果是MRC的编译环境下,要先release掉block对象。
  • 4)在MRC的编译环境下,block如果作为成员参数要copy一下将栈上的block拷贝到堆上(因为block默认是在栈上创建的,如果在定义block的作用于外部使用block那么需要使用copy将block放到堆上)//MRC下:_sucBlock = [callbackBlock copy]; 不copy block会在栈上被回收。
  • 5)将block赋值为空,是解掉循环引用的重要方法。
  • 6)还有一种改法,在block接口设计时,将可能需要的变量作为形参传到block中,从设计上解决循环引用的问题。
  • 7)在多线程环境下(block中的weakSelf有可能被析构的情况下),需要先将self转为strong指针,避免在运行到某个关键步骤时self对象被析构。 第四、第五条合起来有个名词叫weak–strong dance,来自于2011 WWDC Session #322 (Objective-C Advancements in Depth)
  • 以下代码来自AFNetworking,堪称使用weak–strong dance的经典。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    __weak __typeof(self)weakSelf = self;
    AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) {  
        __strong __typeof(weakSelf)strongSelf = weakSelf;  
        strongSelf.networkReachabilityStatus = status;  
        if (strongSelf.networkReachabilityStatusBlock) {  
            strongSelf.networkReachabilityStatusBlock(status);  
        }
    };
  • Review一下上面这段代码,里面玄机不少。
    • 第一行:__weak __typeof(self)weakSelf = self;
    • 如之前第四条所说,为防止callback内部对self强引用,weak一下。
    • 其中用到了__typeof(self),这里涉及几个知识点:
  • a. __typeof、typeof、typeof的区别
    • 恩~~他们没有区别,但是这牵扯一段往事,在早期C语言中没有typeof这个关键字,__typeof、__typeof__是在C语言的扩展关键字的时候出现的。
    • typeof是现代GNU C++的关键字,从Objective-C的根源说,他其实来自于C语言,所以AFNetworking使用了继承自C的关键字。
  • b.对于老的LLVM编译器上面这句话会编译报错,所以在很早的ARC使用者中流行__typeof(&*self)这种写法,
    • 原因如下大致说法是老LLVM编译器会将__typeof转义为 XXX类名 *const __strong的__strong和前面的__weak关键字对指针的修饰又冲突了,所以加上&*对指针的修饰。
    • 第三行:__strong __typeof(weakSelf)strongSelf = weakSelf; 按照之前第五条的说法给转回strong了,这里__typeof()里面写的是weakSelf,里面写self也没有问题,因为typeof是编译时确定变量类型,所以这里写self 不会被循环引用。
    • 第四、五、六行,如果不转成strongSelf而使用weakSelf,后面几句话中,有可能在第四句执行之后self的对象可能被析构掉,然后后面的StausBlock没有执行,导致逻辑错误。
    • 最后第五行,使用前对block判空。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-11-12 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
聊聊springboot项目数据库密码如何加密
在我们日常开发中,我们可能很随意把数据库密码直接明文暴露在配置文件中,在开发环境可以这么做,但是在生产环境,是相当不建议这么做,毕竟安全无小事,谁也不知道哪天密码就莫名其妙泄露了。今天就来聊聊在springboot项目中如何对数据库密码进行加密
lyb-geek
2022/01/07
2.8K0
聊聊springboot项目数据库密码如何加密
巧用Druid数据源实现数据库连接密码的加密解密
一个系统的数据库的连接密码作为一个非常重要的安全数据,其安全非常重要。而在代码的配置文件中直接存放明文密码提交到代码仓库后显然有泄露的风险。
用户3587585
2022/04/14
5.5K0
巧用Druid数据源实现数据库连接密码的加密解密
springboot druid数据库密码加密
其中:publicKey 为公钥 , password为加密后密码,privateKey为私钥
六月的雨在Tencent
2024/03/28
4140
springboot druid数据库密码加密
项目中如何对数据库和redis进行加解密处理?
由于项目的需求要求对数据的账号密码和redis的密码进行加密处理,但又不知道用什么加密的方法,有一些加密的方式很容易破解,正在苦恼的时候问了一下其他的同事只要是加密的不那么一眼看出来就行,心想这是什么心态啊!也是醉了,那既然这样就先按这样做吧!
技术从心
2019/08/06
5K0
项目中如何对数据库和redis进行加解密处理?
springboot之druid数据库密码加密实战
最近接了一个外包单(基于springboot2,连接池为druid),客户经费有限,基本上要啥,啥没有,项目基本上是托管在私人的某gay,某云等,本着让客户放心的原则,就在安全方面多考虑了一点,首先比如数据库密码加密之类的,虽然要是有心要破解也是容易,但至少加密给自己心里一点暗示。。。废话有点多,进入正题,本文主要分为3个部分,第一部分是单个数据源密码加密,第二部分是多个数据源密码加密,第三部分是简要的解密源码分析。
lyb-geek
2022/03/10
1.8K0
springboot之druid数据库密码加密实战
项目中数据库密码没有加密导致了数据泄露!!
作者个人研发的在高并发场景下,提供的简单、稳定、可扩展的延迟消息队列框架,具有精准的定时任务和延迟队列处理功能。自开源半年多以来,已成功为十几家中小型企业提供了精准定时调度方案,经受住了生产环境的考验。为使更多童鞋受益,现给出开源框架地址:
冰河
2021/03/09
7680
SpringBoot项目application配置文件数据库密码上传git暴露问题解决方案
项目中含有配置文件,配置文件中含有数据库的用户名和密码,上传git直接对外网开放。那后果会怎样可想而知。
九转成圣
2024/04/10
1720
SpringBoot项目application配置文件数据库密码上传git暴露问题解决方案
SpringBoot使用Jasypt配置项加密
对于一些安全性要求非常高的企业,是不允许在配置文件中配置明文密码的。因为如果在配置文件明文密码,就有可能存在被泄露的问题。如开发人员使用、严重的点的话就是被黑客盗取。
BUG弄潮儿
2021/01/18
2.7K1
SpringBoot使用Jasypt配置项加密
MySQL连接配置文件密码加密及其在多种连接池上的应用
将配置文件用户相关的信息(例如:密码)进行加密使其以密文形式存在,进行初始化连接池的时候进行解密操作,达到成功创建连接池的目的。
孟君
2019/09/10
4.1K0
Spring拓展接口之BeanFactoryPostProcessor,占位符与敏感信息解密原理
  简单来说,BeanFactoryPostProcessor是spring对外提供的接口,用来拓展spring,能够在spring容器加载了所有bean的信息信息之后、bean实例化之前执行,修改bean的定义属性;有人可能会问,这有什么用?大家还记得spring配置文件中的占位符吗? 我们会在spring配置中配置PropertyPlaceholderConfigurer(继承PropertyResourceConfigurer)bean来处理占位符, 举个例子大家就有印象了
青石路
2019/04/09
1.3K0
Spring拓展接口之BeanFactoryPostProcessor,占位符与敏感信息解密原理
数据库如何加密连接
现在无论是公司的项目还是个人的项目,都会选择将源码托管在Git服务器(Gitee,CODING,云效),只要将源码提交到公网服务器就会存在源码泄露的风险,数据库配置信息作为源码的一部分,一旦出现泄露问题,其产生的损失是无法估量的。
鱼找水需要时间
2023/02/16
2.5K0
数据库如何加密连接
PBE_Password-based encryption(基于密码加密)_项目中你也可以有
中说道了PBE——Password-based encryption(基于密码加密)。我也做测试了一下,现在把我做的效果给大家演示一下:
Hongten
2018/09/13
7490
PBE_Password-based encryption(基于密码加密)_项目中你也可以有
Java 中如何加密配置文件中的数据库账号和密码?
作为程序员每天的开发工作都离不开跟数据库打交道,而且我们的应用程序往往都会配置数据库的链接,那你有没有想过,任何一个能接触到我们项目代码的人员,都可以看到配置文件里面的账号秘密?
Java极客技术
2022/12/04
2.5K0
Java 中如何加密配置文件中的数据库账号和密码?
jasypt对配置文件加密
这里可以看到,redis和mariadb相同的密码,其密文是不一致的。而且配置文件中不需要任何jasypt的配置。程序可以正常启动并解密。
奇门水镜
2024/04/15
5430
SpringBoot配置文件敏感信息加密
SpringBoot配置文件中的内容通常情况下是明文显示,安全性就比较低一些。在application.properties或application.yml,比如mysql登陆密码,redis登陆密码以及第三方的密钥等等一览无余,这次是公安部和一些其他安全部门扫描我们代码前我们自己做整改,这里介绍一个加解密组件,提高一些属性配置的安全性。 jasypt由一个国外大神写了一个springboot下的工具包
胖虎
2019/06/26
3.2K0
SpringBoot配置文件敏感信息加密
拒绝"裸奔",SpringBoot集成Jasypt加密敏感信息
在互联网遍布社会各个角落的时代,伴随着的是安全问题总是层出不穷。 19年4月,根据深圳市人民检察院微信消息,深圳某知名无人机企业的工程师因为泄露公司源代码到开源社区Github上而造成了公司巨大的损失,最终被判处有期徒刑6个月,罚款20万元。
IT学习日记
2022/09/13
1.2K0
拒绝"裸奔",SpringBoot集成Jasypt加密敏感信息
数据库密码配置项都不加密?心也太大了!
这是节选自某个典型的Spring Boot项目的application.properties配置文件。
好好学java
2020/05/27
1.5K0
数据库密码配置项都不加密?心也太大了!
使用Jasypt对SpringBoot配置文件加密
现代互联网充斥着各种攻击、病毒、钓鱼、欺诈等手段,层出不穷。在目前安全形势越来越严重的形势下,我们项目的安全是必须要谨慎对待的问题。项目中的一个安全漏洞处理不好就可能给公司或个人带来严重的损失。
用户1212940
2022/04/13
7110
使用Jasypt对SpringBoot配置文件加密
[Java 安全]加密算法
Base64编码 算法简述 定义 Base64内容传送编码是一种以任意8位字节序列组合的描述形式,这种形式不易被人直接识别。 Base64是一种很常见的编码规范,其作用是将二进制序列转换为人类可读的A
静默虚空
2018/01/05
4K0
[Java 安全]加密算法
springboot使用jasyptdatasource密码加密
<groupId>com.github.ulisesbocchio</groupId>
故久
2019/09/29
1.7K0
springboot使用jasyptdatasource密码加密
推荐阅读
相关推荐
聊聊springboot项目数据库密码如何加密
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验