为对象添加一个释放时触发的block

有时我们需要在一个对象生命周期结束的时候触发一个操作,希望当该对象dealloc的时候调用一个外部指定的block,但又不希望直接hook dealloc方法,这样侵入性太强了.下面贴一段非常简单的实现方式,通过一个category给外部暴露一个block注入的接口,内部将该block封装到一个寄生对象中(Parasite),该寄生对象在dealoc的时候触发block调用,所有的寄生对象通过runtime的AssociatedObject机制与宿主共存亡,从而达到监控宿主生命周期的目的.

实现方案时需要注意的几点:

  • block触发的线程与对象释放时的线程一致,请注意后续操作的线程安全.
  • 不要在block中强引用对象,否则引用循环释放不了;
  • 不要在block中通过weak引用对象,因为此时会返回nil;
    (根据WWDC2011,Session322对对象释放时间的描述,associated objects清除在对象生命周期中很晚才执行,通过被NSObject -dealloc方法调用的object_dispose()函数完成);

代码实现如下。

NSObject+Guard.h:

#import <Foundation/Foundation.h>
@interface NSObject (Guard)
/**
 @brief 添加一个block,当该对象释放时被调用
 **/
- (void)guard_addDeallocBlock:(void(^)(void))block;
@end
NSObject+Guard.m

NSObject+Guard.m:

#import "NSObject+Guard.h"
#import <objc/runtime.h>
@interface Parasite : NSObject
@property (nonatomic, copy) void(^deallocBlock)(void);
@end
@implementation Parasite
- (void)dealloc {
    if (self.deallocBlock) {
        self.deallocBlock();
    }
}
@end
@implementation NSObject (Guard)
- (void)guard_addDeallocBlock:(void(^)(void))block {
    @synchronized (self) {
        static NSString *kAssociatedKey = nil;
        NSMutableArray *parasiteList = objc_getAssociatedObject(self, &kAssociatedKey);
        if (!parasiteList) {
            parasiteList = [NSMutableArray new];
            objc_setAssociatedObject(self, &kAssociatedKey, parasiteList, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        }
        Parasite *parasite = [Parasite new];
        parasite.deallocBlock = block;
        [parasiteList addObject: parasite];
    }
}
@end

Axios 如何实现请求重试?

发布于:17天以前  |  66次阅读  |  详细内容 »

抖音 iOS 工程架构演进

发布于:22天以前  |  65次阅读  |  详细内容 »

【JS】625- Axios 如何缓存请求数据?

发布于:29天以前  |  87次阅读  |  详细内容 »

iOS中触摸事件的传递和响应分析

发布于:1月以前  |  101次阅读  |  详细内容 »

iOS中触摸事件的传递和响应分析

发布于:1月以前  |  113次阅读  |  详细内容 »

探索M1: 安装iOS版本微信/微信读书

发布于:1月以前  |  201次阅读  |  详细内容 »

iOS 稳定性问题治理:卡死崩溃监控原理及最佳实践

发布于:2月以前  |  167次阅读  |  详细内容 »

2021 给 iOS 开发者的一些建议

发布于:2月以前  |  283次阅读  |  详细内容 »

iOS 优化篇 - 启动优化之Clang插桩实现二进制重排

发布于:3月以前  |  280次阅读  |  详细内容 »

抖音品质建设 - iOS启动优化《实战篇》

发布于:3月以前  |  247次阅读  |  详细内容 »

iOS APP 图标版本化

在我们的项目开发过程中,需要频繁打包给测试人员去测试,有时候我们都不知道测试机上安装的版本是否是最新的,这样会造成很多不必要的麻烦和成本。因此我们需要将buildNumber以水印的方式打在APPIcon上,可以很直观的知道当前是哪一个版本。

发布于:3月以前  |  269次阅读  |  详细内容 »

如何实现一个HTTP请求库——axios源码阅读与分析

在前端开发过程中,我们经常会遇到需要发送异步请求的情况。而使用一个功能齐全,接口完善的HTTP请求库,能够在很大程度上减少我们的开发成本,提高我们的开发效率。

发布于:3月以前  |  261次阅读  |  详细内容 »

老司机 iOS 周报 #144 | 2021-01-14

发布于:3月以前  |  305次阅读  |  详细内容 »

快手,快影 iOS App反调试

发布于:4月以前  |  298次阅读  |  详细内容 »

优酷iOS插件化页面架构方法

随着业务不停地迭代,优酷 APP 用于分发视频资源的 UI 控件越写越多,也越来越复杂,并且同时相似相近的代码也非常多。

发布于:5月以前  |  390次阅读  |  详细内容 »

iOS中的内嵌汇编

写一篇在iOS上使用汇编的文章的想法在脑袋里面停留了很久了,但是迟迟没有动手。虽然早前在做启动耗时优化的工作中,也做过通过拦截objc_msgSend并插入汇编指令来统计方法调用耗时的工作,但也只仅此而已。刚好最近的时间项目在做安全加固,需要写更多的汇编来提高安全性(文章内汇编使用指令集为ARM64),也就有了本文

发布于:5月以前  |  417次阅读  |  详细内容 »

77.9K 的 Axios 项目有哪些值得借鉴的地方

Axios 是一个基于 Promise 的 HTTP 客户端,同时支持浏览器和 Node.js 环境。它是一个优秀的 HTTP 客户端,被广泛地应用在大量的 Web 项目中。

发布于:5月以前  |  383次阅读  |  详细内容 »

不会吧,这也行?iOS后台锁屏监听摇一摇

一般情况下,出于省电、权限、合理性等因素考虑,给人的感觉是很多奇怪的需求安卓可以实现,但是iOS就无法实现!今天要介绍的需求也有这种感觉,就是“当 APP 处于后台或锁屏状态时,依旧可以监听到摇一摇,进而触发某些功能,比如:语音播报”。

发布于:6月以前  |  529次阅读  |  详细内容 »

iOS 稳定性:App 被终止的原因

本次 session 主要内容如下: 介绍了后台应用终止的常见原因,并提供了一些优化建议 介绍了 MetricsKit 提供的在代码中获取诊断和性能数据的方法 介绍了 Xcode Metrics Ogranizer 提供的关于线上用户性能数据的可视化报告

发布于:6月以前  |  795次阅读  |  详细内容 »

优酷iOS插件化页面架构方法

随着业务不停地迭代,优酷 APP 用于分发视频资源的 UI 控件越写越多,也越来越复杂,并且同时相似相近的代码也非常多。

发布于:6月以前  |  523次阅读  |  详细内容 »

最多阅读

快速配置 Sign In with Apple 1年以前  |  4157次阅读
使用 GPUImage 实现一个简单相机 1年以前  |  2848次阅读
APP适配iOS11 2年以前  |  2759次阅读
开篇 关于iOS越狱开发 2年以前  |  2733次阅读
在越狱的iPhone设置上使用lldb调试 2年以前  |  2653次阅读
给数组NSMutableArray排序 2年以前  |  2635次阅读
App Store 审核指南[2017年最新版本] 2年以前  |  2584次阅读
所有iPhone设备尺寸汇总 2年以前  |  2508次阅读
UITableViewCell高亮效果实现 2年以前  |  2455次阅读
使用ssh访问越狱iPhone的两种方式 2年以前  |  2388次阅读
关于Xcode不能打印崩溃日志 2年以前  |  2276次阅读
使用ssh 访问越狱iPhone的两种方式 2年以前  |  2175次阅读
为对象添加一个释放时触发的block 2年以前  |  1938次阅读
UIDevice的简单使用 2年以前  |  1936次阅读
使用最高权限操作iPhone手机 2年以前  |  1918次阅读