Objective-C基础之_ weak, _ strong , __ block

上一篇文章中对于block做了一个全面的剖析和理解,那么在OBjective—C的block使用中我们难免会用到以上几个关键字,其实对于__block上篇文章已经做了解释,这篇文章,我会做几个关键字的区别和总结,来加深认识和理解。 
上篇文章知道 clang -rewrite-objc 可以将OC代码转化成C代码C++代码,如果变量加上_ weak修饰,会发现无法转化,提示:cannot create _ weak reference because the current deployment target does not support weak references 我们需要这样解决这个问题:clang -rewrite-objc -fobjc-arc -fobjc-runtime=macosx-10.13 main.m -fobjc-arc代表当前是arc环境 -fobjc-runtime=macosx-10.13:代表当前运行时环境 缺一不可 clang指令

.m 源码

int main(int argc, char * argv[]) {

// @autoreleasepool {

// return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));

int a = 10;

int b = 20;

NSNumber *c = @(123);

__block NSNumber *d = c;

__weak NSNumber *f = c;

void (^myBlock)(void) = ^{

__strong NSNumber *e = f;

NSLog(@"hello world %d, %d, %@, %@, %@, %@", a, b, c, d, f, e);

};

myBlock();

// }

return 0;

}

转化成c代码

// block 结构体

struct __main_block_impl_0 {

struct __block_impl impl;

struct __main_block_desc_0* Desc;

int a;

int b;

NSNumber *__strong c;

NSNumber *__weak f;

__Block_byref_d_0 *d; // by ref

__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _a, int _b, NSNumber *__strong _c, NSNumber *__weak _f, __Block_byref_d_0 *_d, int flags=0) : a(_a), b(_b), c(_c), f(_f), d(_d->__forwarding) {

impl.isa = &_NSConcreteStackBlock;

impl.Flags = flags;

impl.FuncPtr = fp;

Desc = desc;

}

};

// 我们可以看到没有__block修饰的变量和__weak修饰的对象,都没有重新生成一个__Block_byref_d_0 的结构体,只有__block修饰的才会生成这样的结构体

int main(int argc, char * argv[]) {

int a = 10;

int b = 20;

NSNumber *c = ((NSNumber *(*)(Class, SEL, int))(void *)objc_msgSend)(objc_getClass("NSNumber"), sel_registerName("numberWithInt:"), (123));

__attribute__((__blocks__(byref))) __Block_byref_d_0 d = {(void*)0,(__Block_byref_d_0 *)&d, 33554432, sizeof(__Block_byref_d_0), __Block_byref_id_object_copy_131, __Block_byref_id_object_dispose_131, c};

__attribute__((objc_ownership(weak))) NSNumber *f = c;

void (*myBlock)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, f, a, b, c, (__Block_byref_d_0 *)&d, 570425344));

((void (*)(__block_impl *))((__block_impl *)myBlock)->FuncPtr)((__block_impl *)myBlock);

return 0;

}

struct __Block_byref_d_0 {

void *__isa;

__Block_byref_d_0 *__forwarding;

int __flags;

int __size;

void (*__Block_byref_id_object_copy)(void*, void*);

void (*__Block_byref_id_object_dispose)(void*);

NSNumber *__strong d;

};

// 我们可以看到没有加__block的变量,在捕获之后,都会copy出来,不管是值类型还是引用类型的,所以不可以改变内容

static void __main_block_func_0(struct __main_block_impl_0 *__cself) {

__Block_byref_d_0 *d = __cself->d; // bound by ref

NSNumber *__weak f = __cself->f; // bound by copy

int a = __cself->a; // bound by copy

int b = __cself->b; // bound by copy

NSNumber *__strong c = __cself->c; // bound by copy

__attribute__((objc_ownership(strong))) NSNumber *e = f;

NSLog((NSString *)&__NSConstantStringImpl__var_folders_dr_jkts5c395zs9xcx0bt_r7fx40000gn_T_main_188e34_mi_0, a, b, c, (d->__forwarding->d), f, e);

}

通过上述的源码,我们可以看出,只有__ block 修饰的局部变量才会生成一个结构体,这个结构体包含了变量,而block的结构体则是一个变成了结构体的指针,所以内部修改指针指向内容是可以的,而对于没有修饰的变量,值变量则是重新声明一个变量赋值相同,引用类型则是重新申明变量,指针copy,所以在内部都是无法修改外部变量的值的。

综上所述,__ block :修饰的外部局部变量值和引用类型,都会重新生成包裹该变量的结构体,block本质结构体会声明这个结构体的指针,所以可以直接修改外部局部变量;可修饰值变量和引用变量(即普通类型和对象类型的变量); 
没有修饰的变量:值类型和引用类型都会重新生成一个变量,值类型重新生成一个变量,将局部变量的值赋值给他;引用类型的变量,生成一个新指针,指向这个指针的copy,强引用; 
weak :没有重新生成包裹变量的结构体,重新声明一个弱引用指针,指向这个指针的copy体,所以不可以在内部修改变量的值;只能修饰引用类型的变量,所以 weak 修饰可以防止循环引用; 
__strong:一般使用像如下代码

// typeof() 函数只是返回参数的类型

__weak typeof(self) weakSelf = self;

void (^myBlock)(void) = ^{

__strong typeof(self) strongSelf = weakSelf;

}

block内部对变量生成一个强引用,防止在Block函数体执行过程中,变量被释放,block函数体执行完,引用计数器-1

原文地址:https://www.cnblogs.com/wannaGoBoy/p/9052700.html

时间: 2024-10-02 23:19:03

Objective-C基础之_ weak, _ strong , __ block的相关文章

Oracle SQL语言基础及环境准备_超越OCP精通Oracle视频教程培训26

Oracle SQL语言基础及环境准备_超越OCP精通Oracle视频教程培训26 本课程介绍: Oracle视频教程,风哥本套oracle教程培训是<<Oracle数据库SQL语言实战培训教程>>的第1/5套:SQL语言之基础入门及环境准备.主要学习Oracle数据库SQL语言基础介绍.PL/SQL语言介绍.数据库SQL对象与数据类型介绍.SQL语言实战环境准备等. Oracle SQL语言之基础及环境准备,课程内容详细如下: Oracle数据库SQL语言基础介绍Oracle数据

Java基础知识综合练习_使用集合存储_高级银行系统的搭建(注册、登录、存取款、本行转账、跨行转账、销户、特殊操作参数、多个客户对象存入到银行类的集合,多个银行对象存入总测试类集合)

Java基础知识综合练习_使用集合存储_高级银行系统的搭建(注册.登录.存取款.本行转账.跨行转账.销户.特殊操作参数.多个客户对象存入到银行类的集合,多个银行对象存入总测试类集合) 1) 定义bank类 属性有银行名称和存放客户的ArrayList集合, 有开户方法. 销户方法. 存钱方法. 取钱方法. 转账方法(本行转账.跨行转账) 2) 定义customer类 属性有账户名.密码.余额 3) 定义测试类创建一个银行集合用于存放bank对象创建几个bank对象:分别叫华夏银行.工商银行.招商

算法基础_递归_求杨辉三角第m行第n个数字

问题描述: 算法基础_递归_求杨辉三角第m行第n个数字(m,n都从0开始) 解题源代码(这里打印出的是杨辉三角某一层的所有数字,没用大数,所以有上限,这里只写基本逻辑,要符合题意的话,把循环去掉就好): import java.util.Scanner; /** * 求杨辉三角第m层第n个数字 * @author Administrator * */ public class Demo05 { public static int f(int m,int n) { if(n==0)return 1

【IOS学习基础】weak和strong、懒加载、循环引用

一.weak和strong 1.理解 刚开始学UI的时候,对于weak和strong的描述看得最多的就是“由ARC引入,weak相当于OC中的assign,但是weak用于修饰对象,但是他们都不会造成引用计数加1:而strong则相当于OC中规定retain,它会造成引用计数加1”. ARC的原理:只要还有一个变量指向对象,对象就会保持在内存中.当指针指向新值,或者指针不再存在时,相关联的对象就会自动释放.这条规则对于实例变量.synthesize属性.局部变量都是适用的 strong指针能够保

(素材源码)猫猫学IOS(三十六)UI之手势事件旋转_缩放_拖拽

猫猫分享,必须精品 原创文章,欢迎转载.转载请注明:翟乃玉的博客 地址:http://blog.csdn.net/u013357243?viewmode=contents 源码:http://download.csdn.net/detail/u013357243/8671943 效果 完成一个图片的捏合缩放,拖拽,旋转动作. 代码:NYViewController.m // // NYViewController.m // 旋转_缩放_拖拽 // // Created by apple on 1

【iOS面试系列-1】iOS中@property 后assign,copy,retain,weak,strong的意义与区别(必考-必须详细掌握)

来源:网络 assign: 普通(简单)赋值,一般常用于基本数据类型,常见委托设计模式,一次来防止循环引用.不更改索引计数(Reference Counting). 对基础数据类型 (NSInteger,CGFloat)和C数据类型(int, float, double, char, 等等) retain:保留计数,获得到了对象的所有权,引用计数在原有基础上+1.释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1 .我们给那块内存设一个引用计数,当内存被分配并且赋值给a时,引用

三口之家2014年买房理财规划:组合贷缓月供压力 理财资讯 财富故事 理财案例_新浪财经_新浪网

投资与理财记者 吴辉 春暖花开时,江苏常州的读者陈芊芊致信<投资与理财>,诉说她的买房计划.她纠结于要不要现在买房,担心买房后,生活压力变大,影响了现在的生活质量,并希望我们的理财师能给她一些建议,告诉她怎样的理财规划更为合理? 芊芊今年32岁了,目前在一个集团公司上班,税后年收入55000元,年底其他收入29000元,有社保和公积金.但公积金每月交的钱只有300元,而且存款才一年.老公税后年收入60000元,无社保,无公积金,也没有任何商业保险.年底时,老公会交给她3 0 0 0 0元存款.

个体户理财有讲究:保险投资养老三者要兼顾 理财 个体户 养老_新浪财经_新浪网

黄先生今年37岁,妻子刘女士35岁,夫妻二人共同经营了一家综合性批发部.女儿10岁,读四年级,儿子5岁,上幼儿园.家庭年收入35万元,家庭每月支出8500元,其中消费在衣食方面3000元,孩子每月学费2000元.有一辆家庭用车和一辆货物运输车共值20万元,房产一套,市值80万元,银行一年期定期存款100万元,平常流动资金30万元. 理财目标 随着两个孩子渐渐长大,支出会逐渐增加,夫妻二人想让孩子接受最好的教育,必要时可以出国留学.而面临同行业竞争日益激烈,经商收益不稳定,因此,黄先生很为今后孩子

IOS_地图_定位_天气预报_Block回调_单例

H:/1021/00_block回调.h /* 通过block回调 定义block代码块,目的是解析完成之后调用 返回值是 void 参数是 数组,里面的每个成员是一个NSString*/ typedef void(^WeatherFinishedBlock)(NSArray *dataList); @interface WeatherXMLPaser : NSObject // 解析器解析数据,参数1是要解析的数据,参数2是解析完毕回调的代码块 - (void)parserWeatherDat