zoukankan      html  css  js  c++  java
  • 为对象添加一个释放时触发的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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #import <Foundation/Foundation.h>

    @interface NSObject (Guard)

    /**
    @brief 添加一个block,当该对象释放时被调用
    **/
    - (void)guard_addDeallocBlock:(void(^)(void))block;

    @end

    NSObject+Guard.m

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    #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
  • 相关阅读:
    【AtCoder Regular Contest 080E】Young Maids [堆][线段树]
    【AtCoder Grand Contest 007E】Shik and Travel [Dfs][二分答案]
    【Codeforces858F】Wizard's Tour [构造]
    【AtCoder Grand Contest 001F】Wide Swap [线段树][拓扑]
    【AtCoder Grand Contest 012C】Tautonym Puzzle [构造]
    【Foreign】动态规划 [分治][DP]
    【BZOJ2683】简单题 [分治][树状数组]
    【BZOJ4237】稻草人 [分治][单调栈]
    【BZOJ3745】Norma [分治]
    【BZOJ4552】【HEOI2016】排序 [二分答案][线段树]
  • 原文地址:https://www.cnblogs.com/xiao-love-meng/p/5757560.html
Copyright © 2011-2022 走看看