当前位置: 首页 > news >正文

Objective-C使用块枚举的细节

对元素类型的要求

在 Objective-C 中,NSArray 只能存储对象类型,而不能直接存储基本类型(例如 int)。但是,可以将基本类型封装在 NSNumber 等对象中,然后将这些对象存储在 NSArray 中。这样,enumerateObjectsUsingBlock: 方法中的 obj 仍然是指向这些对象的指针。

NSArray *array = @[@1, @2, @3];
[array enumerateObjectsUsingBlock:^(NSNumber *obj, NSUInteger idx, BOOL *stop) {int value = [obj intValue];NSLog(@"Object: %@, Int Value: %d, Address: %p", obj, value, obj);
}];

obj 是一个指针变量,局部变量

obj 和 array 中对应位置的元素指向相同的内存地址,但它们不是同一个指针变量,而是两个指向同一对象的不同变量。

在 -enumerateObjectsUsingBlock: 方法中,块枚举会遍历数组,并将每个元素的指针赋值给 obj。因此,obj 是一个局部变量,在每次迭代时指向数组中当前遍历的元素。尽管它们指向同一对象,但 obj 是块中的局部变量,而数组中的元素是数组中的存储单元。

NSArray *array = @[@"one", @"two", @"three"];
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {NSLog(@"Object: %@, obj Address: %p, obj Pointer Address: %p, array[idx] Address: %p, array[idx] pointer Address: %p", obj, obj, &obj, array[idx], &array[idx]);
}];

循环引用问题

在 Objective-C 中使用 enumerateObjectsUsingBlock 时,同样需要注意循环引用问题。enumerateObjectsUsingBlock 会将块传递给枚举方法,如果块捕获了对自身或外部对象的强引用,这可能导致循环引用,尤其是当这个对象也强引用调用该块的对象时。

示例说明

假设有一个类 MyClass,其实例方法使用 enumerateObjectsUsingBlock

@interface MyClass : NSObject
@property (nonatomic, strong) NSArray *array;
@end@implementation MyClass- (void)enumerateArray {[self.array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {// 这里使用了 selfNSLog(@"%@", self);}];
}@end

在上述代码中,块捕获了 self 的强引用。如果 self 对象持有 array,这就形成了一个循环引用,导致 self 无法被释放。

解决方案

使用弱引用来打破循环引用,可以使用 __weak__block 关键字:

@implementation MyClass- (void)enumerateArray {__weak typeof(self) weakSelf = self;[self.array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {// 这里使用了弱引用的 self__strong typeof(weakSelf) strongSelf = weakSelf;if (strongSelf) {NSLog(@"%@", strongSelf);}}];
}@end

在这个修改后的代码中,使用 __weakself 的弱引用传递到块内,然后在块内将其转换为强引用以确保在使用过程中对象的生命周期被正确管理。

相关文章:

  • 如何构建智能聊天系统
  • Zigbee智能家居数据中心:微信小程序实时掌控家居传感器信息
  • Java面试题-锁
  • 【前端项目笔记】7 商品管理
  • 玩转springboot之springboot扩展SpringMVC
  • Elasticsearch实战教程: 如何在海量级数据中进行快速搜索
  • 行业模板|DataEase旅游行业大屏模板推荐
  • SpringMVC页面加载不出来,静态资源全部自动https
  • 反射--通俗易懂
  • ModuleNotFoundError: No module named ‘_sysconfigdata_x86_64_conda_linux_gnu‘
  • YOLO在目标检测与视频轨迹追踪中的应用
  • 使用hadoop进行数据分析
  • library source does not match the bytecode for class SpringApplication
  • Ajax异步请求 axios
  • 深⼊理解 JVM 底层原理、垃圾回收机制,能通过mat、jstat进行JVM参数调优
  • 【Leetcode】104. 二叉树的最大深度
  • 2018以太坊智能合约编程语言solidity的最佳IDEs
  • angular2开源库收集
  • exports和module.exports
  • extjs4学习之配置
  • jQuery(一)
  • JS创建对象模式及其对象原型链探究(一):Object模式
  • oschina
  • PHP的Ev教程三(Periodic watcher)
  • Python打包系统简单入门
  • SpringCloud集成分布式事务LCN (一)
  • 短视频宝贝=慢?阿里巴巴工程师这样秒开短视频
  • 设计模式 开闭原则
  • JavaScript 新语法详解:Class 的私有属性与私有方法 ...
  • 新年再起“裁员潮”,“钢铁侠”马斯克要一举裁掉SpaceX 600余名员工 ...
  • ​​​​​​​sokit v1.3抓手机应用socket数据包: Socket是传输控制层协议,WebSocket是应用层协议。
  • ​LeetCode解法汇总2670. 找出不同元素数目差数组
  • ​虚拟化系列介绍(十)
  • # MySQL server 层和存储引擎层是怎么交互数据的?
  • ######## golang各章节终篇索引 ########
  • (1/2)敏捷实践指南 Agile Practice Guide ([美] Project Management institute 著)
  • (31)对象的克隆
  • (4)logging(日志模块)
  • (5)STL算法之复制
  • (C语言版)链表(三)——实现双向链表创建、删除、插入、释放内存等简单操作...
  • (八)Spring源码解析:Spring MVC
  • (附源码)springboot宠物医疗服务网站 毕业设计688413
  • (附源码)ssm考生评分系统 毕业设计 071114
  • (函数)颠倒字符串顺序(C语言)
  • (免费分享)基于springboot,vue疗养中心管理系统
  • (实战)静默dbca安装创建数据库 --参数说明+举例
  • (五)c52学习之旅-静态数码管
  • (译)2019年前端性能优化清单 — 下篇
  • .java 指数平滑_转载:二次指数平滑法求预测值的Java代码
  • .NET Core 项目指定SDK版本
  • .NET/C# 利用 Walterlv.WeakEvents 高性能地定义和使用弱事件
  • .NET开发不可不知、不可不用的辅助类(三)(报表导出---终结版)
  • /dev/VolGroup00/LogVol00:unexpected inconsistency;run fsck manually
  • @EnableWebSecurity 注解的用途及适用场景
  • [ Linux ] Linux信号概述 信号的产生