我们可以自己创建一个 A 类,然后在“宿主对象”和“值对象”建立 weak 关系的时候,偷偷地创建一个 A 类的实例 a,绑定在 “值对象” 上。
当“值对象”销毁后,这个 a 也会被销毁。而 A 类是轮子的内部类,其 dealloc 方法可以随意改造。
这样就可以把 宿主对象.某属性 = nil 这段代码写在 A 类的 dealloc 方法里。
由于 [a dealloc][值对象 dealloc] 是一起执行的,我们便做到在不改原有类的情况下捕获原有类的 dealloc 方法
总结来说在 Category 里我们要用关联对象的方法让“值类型”强引用 a。
 
/** 宿主类的分类实现 */
@implementation MUHostClass (Association)
const static char kValueObject = '0';
- (void)setValueObject:(MUValueClass *)valueObject {
  objc_setAssociatedObject(self, &kValueObject, valueObject, OBJC_ASSOCIATION_ASSIGN);
  /** * 1. 虽然这里没有循环引用,但是还是需要把弱引用丢给 block *
   因为 valueObj 持有 weakTask,weakTask 持有 block,block 持有 self *
   因此 self 至少要等到 valueObj 销毁后才能销毁。严重影响到 self 的生命周期 **/
   __weak typeof(self) wself = self;
  [valueObject setWeakReferenceTask:^{
    objc_setAssociatedObject(wself, &kValueObject, nil, OBJC_ASSOCIATION_ASSIGN); }
  ];
}
- (MUValueClass *)valueObject {
  return objc_getAssociatedObject(self, &kValueObject);
}
@end
/** 给所有的类添加扩展 */
@implementation NSObject (MUWeakTask)
static const char kWeakTask = '0';
- (void)setWeakReferenceTask:(TaskBlock)task {
  MUWeakTask *weakTask = [MUWeakTask taskWithTaskBlock:task];
  objc_setAssociatedObject(self, &kWeakTask, weakTask, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
/** 传说中的 A 类 */
@implementation MUWeakTask
- (instancetype)initWithTaskBlock:(TaskBlock)taskBlock{
  self = [super init];
  if (self) {
    _taskBlock = [taskBlock copy];
  }
  return self;
}
+ (instancetype)taskWithTaskBlock:(TaskBlock)taskBlock {
  return [[self alloc] initWithTaskBlock:taskBlock];
}
- (void)dealloc {
  if (self.taskBlock) {
    self.taskBlock();
  }
}
@end

runtime实现weak属性的更多相关文章

  1. runtime 如何实现 weak 属性

    出题者简介: 孙源(sunnyxx),目前就职于百度 整理者简介:陈奕龙(子循),目前就职于滴滴出行. 转载者:豆电雨(starain)微信:doudianyu 要实现 weak 属性,首先要搞清楚 ...

  2. weak属性需要在dealloc中置nil么?

    出题者简介: 孙源(sunnyxx),目前就职于百度 整理者简介:陈奕龙(子循),目前就职于滴滴出行. 转载者:豆电雨(starain)微信:doudianyu 不需要. 在ARC环境无论是强指针还是 ...

  3. OC 中的 weak 属性是怎么实现的?

    OC 中的 weak 属性是怎么实现的,为什么在对象释放后会自动变成 nil?本文对这个问题进行了一点探讨.环境 mac OS Sierra 10.12.4 objc709参考答案 搜索后发现runt ...

  4. Runtime(动态添加属性)

    下面通过一个实例展示一下Runtime(动态添加属性)的用法 下面对运行时添加属性用到的策略参数进行补充: 这样看来,前面的NSString* name用的策略是retain nonatomic就知道 ...

  5. runtime如何实现weak属性

    首先了解weak是一种非拥有关系,属性所值对象销毁时,属性值会清空(nil). Runtime对注册的类会进行布局,对于weak对象会放入hash表中,用weak指向的内存地址作为key,当对象引用计 ...

  6. ios专题 - objc runtime 动态增加属性

    objective-c中,有类别可以在不修改源码的基础上增加方法:近排在看别人的开源代码时,发现还可以动态增加属性.而且是在运行时,太牛B了. 使用运行时库,必须要先引入 objc/runtime.h ...

  7. objc runtime 动态增加属性

    objective-c中,有类别可以在不修改源码的基础上增加方法:近排在看别人的开源代码时,发现还可以动态增加属性.而且是在运行时,太牛B了. 使用运行时库,必须要先引入 objc/runtime.h ...

  8. delegate 为什么用 weak属性

    weak指针主要用于“父-子”关系,父亲拥有一个儿子的strong指针,因此是儿子的所有者:但是为了阻止所有权回环,儿子需要使用weak指针指向父亲:你的viewcontroller通过strong指 ...

  9. runtime怎么添加属性、方法等

    ivar表示成员变量 class_addIvar class_addMethod class_addProperty class_addProtocol class_replaceProperty

随机推荐

  1. WebRTC 配置环境

    复制文件到指定文件路径 cp -rf /home/leehongee/LeeHonGee/jdk1.7.0_45 /usr/lib/jvm 创建文件夹   mkdir jvm 修改环境变量 sudo ...

  2. json转 PostMan bulk Edit application/x-www-form-urlencoded 需要的格式

    {?\n\s*"([^"]+)"\s*:\s*"?([^,"]+)"?\s*,?}? $1:$2\n PostMan需要的格式. json转 ...

  3. android 编程之 PopupWindow 窗口的弹出

    PopupWindow 是一个可以显示在当前 Activity 之上的浮动容器,PopupWindow 弹出的位置是能够改变的,按照有无偏移量,可以分为无偏移和有偏移两种:按照参照对象的不同又可以分为 ...

  4. 利用selenroid扩展uiautoamtor的webview解析能力

    uiautomator是一个非侵入式框架,但是webview解析能力很弱.为了改进webview的支持,可以考虑把webdriver或者selenroid整合进来. 具体接入可参考:http://se ...

  5. 10.13 Django随笔

    2018-10-13 14:20:59 越努力,越幸运! 永远不要高估自己! Django的渲染是在render()时候渲染的,然后把字符串传给浏览器 Django请求流程, 跨域 参考链接: htt ...

  6. 常用Common集合

    Log using System; using System.IO; using System.Linq; using System.Text; namespace Common { public c ...

  7. 恢复制作了系统盘的U盘

    制作了系统盘的U盘通常容量会变得很小(比如用win32制作的系统盘) 此时在系统安装完成之后就要把U盘恢复,否则就无法正常使用了 步骤: 1.win+r打开程序搜索框,输入cmd打开dos窗口 2.在 ...

  8. [No0000CE]检测非空格字符作为密码的密码强度

    Regex.Replace(pwd, "^(?:([a-z])|([A-Z])|([0-9])|(.)){6,}|(.)+$", "$1$2$3$4$5").L ...

  9. 1.7Oob同类中不同方法间的互相调用

    import java.util.Scanner; public class Bill { public static final double RATE=150.0; 这里没有创建getter和se ...

  10. 使用shell删除目录下几天前生成文件方法

    find /dbfdumpdir/*full* -mtime +21 -exec rm -rf {} \; 这个shell可以删除目录/dbfdumpdir下面21天前生成的,文件名包含full的文件 ...