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];
}

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

相关推荐
_瑞16 分钟前
试图教会你用 Xcode Instruments
前端·ios·xcode
JoyCong19981 小时前
为什么连接到被控后,客户端会自动锁定+出现锁屏界面?
macos·智能手机·电脑·远程工作·远程操作
芳草萋萋鹦鹉洲哦6 小时前
【git】重新生成并添加 SSH Key(Mac)
git·macos·ssh
2501_915909067 小时前
iOS应用性能监控 Instruments工具与崩溃日志分析完整指南
android·ios·小程序·https·uni-app·iphone·webview
iOS开发上架哦1 天前
Android代码混淆与iOS加固技术详解
后端·ios
2501_915918411 天前
详解iOS App上架至App Store的全流程步骤与注意事项
android·macos·ios·小程序·uni-app·cocoa·iphone
库奇噜啦呼1 天前
【iOS】weak底层实现
macos·ios·cocoa
jike_20261 天前
iPhone会议录音转文字怎么操作?科会通实测:支持离线录音与多人声纹识别的苹果AI会议纪要工具
人工智能·cocoa·iphone
2601_961593421 天前
视频分辨率太低?Topaz Video AI v1.6.0 让画质跃升
人工智能·macos·音视频
17715574311 天前
Mac 上 Ruby、gem、rvm、CocoaPods 四者关系通俗讲清楚
macos·ruby·cocoapods