Objective-C使用块枚举的细节

对元素类型的要求

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

objc 复制代码
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 是块中的局部变量,而数组中的元素是数组中的存储单元。

objc 复制代码
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:

objc 复制代码
@interface MyClass : NSObject
@property (nonatomic, strong) NSArray *array;
@end

@implementation MyClass

- (void)enumerateArray {
    [self.array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        // 这里使用了 self
        NSLog(@"%@", self);
    }];
}

@end

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

解决方案

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

objc 复制代码
@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

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

相关推荐
茶底世界之下6 小时前
花瓣要更柔和,还是更有反差?用 Awaking 做一次对比度取舍
ios
Anhty1 天前
2026最新免费手机音频处理工具 !!
android·功能测试·ios·智能手机·音视频
2501_915909061 天前
iOS应用从开发到上架App Store的完整发布流程与步骤指南
android·ios·小程序·https·uni-app·webview
初雪云1 天前
UniApp 云打包拿到 IPA 后,真正的发布工作才刚开始
ios·自动化·编辑器·产品经理·iphone
Lancker1 天前
没有 Mac 也能上架 iOS:GitHub Actions 全自动构建 + 签名 + TestFlight 送审实录
macos·ios·github
茶底世界之下1 天前
晚霞要多暖?用 Awaking 只改色温做一次取舍
ios
酒神dnspup1 天前
多地区网站可用性监控怎么做?DNSPup 从基线到告警的完整实战
运维·ios·云计算·iphone·dns·网络监控
福兮说2 天前
浏览器里把 iPhone 的 HEIC 转成 JPG:Chrome 解不开、转完大了七成、拍摄时间全丢,六个坑实测
前端·javascript·图像处理·chrome·ios·iphone·heic
茶底世界之下2 天前
时间线效果层,为什么不能只复用一个处理器?
ios·swift
ZZH_AI项目交付2 天前
实时字幕负责快,本地录音负责不丢:一个 iOS 录音功能为什么需要两条链路
ios·ai编程