若是一个类在释放事后,dealloc方法没有执行,那么就表明着这个类还被其余对象所引用,引用计数不为0,这样就形成了内存泄露json
昨天其余业务线开发告知他所依赖的我这边的父类VC的-dealloc 方法不执行,叫我跟一下函数
因而我很快的想到-dealloc没执行,确定是循环引用内存泄露之类的问题,因而打开instrument,复现着触发步骤,一个红点,两个红点;嘿,就是你了,结果查找call trees事后就蒙蔽了,报错是jsonmodel的实例方法有问题,难道是某个子类化的JsonModel对象引用了这个VC? 可是这个类有接近两千行,我怎么看?指针
因而小组大神出场,其在使用了一番instrument事后,发现确实这个VC在释放事后引用计数不为0,可是从各个内存的使用状况啊,调用堆栈啊并看不出错误是出如今哪里(他说instrument改版后不太会用了),在得知个人业务需求事后,因而叫我去用最笨的办法去解决-- 把全部改动屏蔽掉,而后逐个取消屏蔽,看内存泄露在哪个方法里面code
因而尝试,定位,尝试,定位对象
最终找到循环引用的地方:blog
在block外面是把self指针置为weak了的,可是进入block事后,倒是仍然使用的是强self指针去调用的本类方法,这样一来,便形成了经典的循环引用的问题:内存
self ---> block block ---> self
因而VC里面就没办法释放掉,这就是形成VC的dealloc方法未能执行的缘由开发
#define weakify(...) \\ autoreleasepool {} \\ metamacro_foreach_cxt(rac_weakify_,, __weak, __VA_ARGS__) #define strongify(...) \\ try {} @finally {} \\ _Pragma("clang diagnostic push") \\ _Pragma("clang diagnostic ignored \\"-Wshadow\\"") \\ metamacro_foreach(rac_strongify_,, __VA_ARGS__) \\ _Pragma("clang diagnostic pop")
他们的做用主要是在block内部管理对self的引用:input
@weakify(self); // 定义了一个__weak的self_weak_变量 [RACObserve(self, name) subscribeNext:^(NSString *name) { @strongify(self); // 局域定义了一个__strong的self指针指向self_weak self.outputLabel.text = name; }];
这两个宏必定成对出现,先weak再strong.能够很好的管理Block内部对self的引用。 固然你若是是一个不爱用黄色宏的盆友的话,你能够用原生代码写出来it
__weak typeof(self) weakSelf = self; self.Button.rac_command = [[RACCommand alloc] initWithEnabled:textSig signalBlock:^RACSignal *(NSString * input) { __strong typeof(weakSelf) strongSelf = weakSelf; return nil; }];
在使用instrument的过程当中可能由于某些缘由,检测不到具体的某个函数的内存泄露,这个时候就不能依赖instrument了(也多是本渣不太懂怎么调,欢迎指正),这个时候就只能使用最笨的办法 --- 还原二分法来trick了