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

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

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

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

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. 自定义引用计数的实现示例

@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 单例对象

@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 特殊内存管理

@implementation PooledObject

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

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

4. 注意事项

4.1 线程安全

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

4.2 内存泄漏防护

- (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. 最佳实践

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

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


http://www.kler.cn/a/469963.html

相关文章:

  • 【银河麒麟高级服务器操作系统实例】tcp半链接数溢出分析及处理全过程
  • jenkins入门6 --拉取代码
  • 66.基于SpringBoot + Vue实现的前后端分离-律师事务所案件管理系统(项目 + 论文)
  • vue3组件化开发优势劣势分析,及一个案例
  • 【数据可视化-11】全国大学数据可视化分析
  • 智能客户服务:科技如何重塑客户服务体验
  • Cursor 实战技巧:好用的提示词插件Cursor Rules
  • 深度解读 “驭风行动”
  • Latex中inproceedings 和 article的区别
  • 【wiki知识库】08.添加用户登录功能--后端SpringBoot部分
  • mac 使用zip2john破解zip压缩包密码
  • Ruby语言的编程范式
  • idea全局替换显示不全(ctrl+shift+R)
  • Teleport 传送
  • 前端开发中页面优化的方法
  • LLM之RAG实战(五十一)| 使用python和Cypher解析PDF数据,并加载到Neo4j数据库
  • unity3d——3D动画学习day01 状态机相关参数
  • HackMyVM-Always靶机的测试报告
  • Linux文件系统权限
  • 2024 高级爬虫笔记(五)mysql、MongoDB、reids
  • 【Java数据结构】二叉树
  • 内网穿透的应用-自托管文件分享系统PicoShare搭建流程与远程共享实战教程
  • 大数据-240 离线数仓 - 广告业务 测试 ADS层数据加载 DataX数据导出到 MySQL
  • LInux单机安装Redis
  • 现代前端框架
  • html+css+js网页设计 体育 中满体育4个页面