iOS - 自定义引用计数(MRC)

自定义引用计数(Custom Reference Counting)是指类可以通过重写 retain/release 等方法来实现自己的引用计数管理机制。这通常用于特殊场景下的内存管理优化。

1. 判断是否使用自定义引用计数

objectivec 复制代码
inline bool 
objc_object::hasCustomRR() {
    // 检查类是否实现了自定义的引用计数方法
    return ISA()->hasCustomRR();
}

// 调用路径
id objc_object::retain() {
    if (fastpath(!ISA()->hasCustomRR())) {
        // 使用系统默认的引用计数机制
        return sidetable_retain();
    } else {
        // 使用类自定义的引用计数机制
        return ((id(*)(objc_object *, SEL))objc_msgSend)(this, @selector(retain));
    }
}

2. 自定义引用计数的实现示例

objectivec 复制代码
@interface CustomObject : NSObject

@property (nonatomic, assign) NSUInteger customRefCount;

@end

@implementation CustomObject

- (id)retain {
    @synchronized(self) {
        self.customRefCount++;
    }
    return self;
}

- (void)release {
    BOOL shouldDealloc = NO;
    @synchronized(self) {
        self.customRefCount--;
        if (self.customRefCount == 0) {
            shouldDealloc = YES;
        }
    }
    
    if (shouldDealloc) {
        [self dealloc];
    }
}

- (NSUInteger)retainCount {
    @synchronized(self) {
        return self.customRefCount;
    }
}

3. 使用场景

3.1 单例对象

objectivec 复制代码
@implementation MySingleton

+ (instancetype)sharedInstance {
    static MySingleton *instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[super allocWithZone:NULL] init];
    });
    return instance;
}

// 防止释放
- (id)retain {
    return self;
}

- (oneway void)release {
    // 不执行任何操作
}

- (id)autorelease {
    return self;
}

3.2 特殊内存管理

objectivec 复制代码
@implementation PooledObject

// 对象池中的对象
- (id)retain {
    // 不增加引用计数,而是返回到对象池
    [[ObjectPool sharedPool] markAsInUse:self];
    return self;
}

- (void)release {
    // 不真正释放,而是返回到对象池
    [[ObjectPool sharedPool] returnToPool:self];
}

4. 注意事项

4.1 线程安全

objectivec 复制代码
- (id)retain {
    @synchronized(self) {
        // 确保线程安全的引用计数操作
        _customRefCount++;
    }
    return self;
}

4.2 内存泄漏防护

objectivec 复制代码
- (void)release {
    BOOL shouldDealloc = NO;
    {
        @synchronized(self) {
            _customRefCount--;
            if (_customRefCount == 0) {
                shouldDealloc = YES;
            }
        }
    }
    
    // 在同步块外执行 dealloc
    if (shouldDealloc) {
        [self dealloc];
    }
}

5. 优缺点

优点:

  1. 可以实现特殊的内存管理策略
  2. 适合特定场景的优化
  3. 可以实现对象池等高级功能

缺点:

  1. 增加代码复杂度
  2. 可能引入bug
  3. 需要格外注意线程安全
  4. 可能影响系统的内存管理优化

6. 最佳实践

objectivec 复制代码
@implementation CustomRefCountObject

// 1. 清晰的文档
/**
 * 这个类使用自定义引用计数来实现对象池
 * 注意:不要直接创建实例,请使用 getFromPool 方法
 */

// 2. 完整的方法实现
- (id)retain {
    if (_customManaged) {
        return [self customRetain];
    }
    return [super retain];
}

// 3. 防御性编程
- (void)release {
    if (_customManaged) {
        [self customRelease];
        return;
    }
    [super release];
}

// 4. 调试支持
- (NSUInteger)retainCount {
    if (_customManaged) {
        return [self customRetainCount];
    }
    return [super retainCount];
}

自定义引用计数应该谨慎使用,只在确实需要的特殊场景下采用。大多数情况下,系统默认的引用计数机制就足够了。

相关推荐
Batac_蝠猫10 小时前
iOS - 原子操作
ios·objective-c·cocoa
真想骂*11 小时前
iOS开发指南:保护服务器密码的安全存储与处理技巧
服务器·安全·ios
小钱c713 小时前
关于Mac使用VSCode连接虚拟机
ide·vscode·macos
1024小神13 小时前
在swiftui中使用Alamofire发送请求获取github仓库里的txt文件内容并解析
ios·github·swiftui
Batac_蝠猫19 小时前
iOS - Tagged Pointer
ios
计科土狗20 小时前
c++程序设计(第3版)系列教程
开发语言·c++·cocoa
SoraLuna21 小时前
「Mac畅玩鸿蒙与硬件53」UI互动应用篇30 - 打卡提醒小应用
macos·ui·harmonyos
Danny_姜21 小时前
荒腔走板Mac电脑本地部署 LLM
macos
伊织code21 小时前
报错 - decord 在 macOS Silicon 安装失败
macos·m2·decord·silicon·eva-decord