编程的有效方法--避免循环引用

1、引起循环引用的原因

  1> A拥有B,B拥有C。当C需要销毁时,发现被B拥有,当B需要销毁时,发现被A用有,从而导致内存泄漏。如NSTimer(NSRunloop拥有NSTimer,NSTimer拥有self);

  2> A拥有B,B拥有A。如block作为属性时,使用代理时;

2、打破循环引用

  打破循环引用的关键在于解除上述的拥有关系;

3、出现循环引用的三种情况

  NSTimer

  定时器跟Runloop协同工作,Runloop是拥有NSTimer的,同时NSTimer是拥有self的,这就导致如果没有有效地调用invalidate方法,就会导致NSTimer会一直工作下去,解决办法可以改变NSTimer的target,使target指向一个无需我们管理的一个对象,如单利:

@interface NSTimer (XXBlocksSupport)

+ (NSTimer *)xx_scheduledTimerWithTimeInterval:(NSTimeInterval)interval
                                         block:(void(^)())block
                                       repeats:(BOOL)repeats;

@end

@implementation NSTimer (XXBlocksSupport)

+ (NSTimer *)xx_scheduledTimerWithTimeInterval:(NSTimeInterval)interval
                                         block:(void(^)())block
                                       repeats:(BOOL)repeats
{
    return [self scheduledTimerWithTimeInterval:interval
                                          target:self
                                        selector:@selector(xx_blockInvoke:)
                                        userInfo:[block copy]
                                         repeats:repeats];
}

+ (void)xx_blockInvoke:(NSTimer *)timer {
    void (^block)() = timer.userinfo;
    if(block) {
        block();
    }
}

@end
时间: 2024-08-13 00:08:03

编程的有效方法--避免循环引用的相关文章

20180711-flask高级编程-循环引用

16. 路径加了<>,就会被识别为一个参数,而不是固定的url字符串 16.1 编程原则:视图函数里面要尽可能间接,函数要见名知意,不能将细节全部写到视图函数里面,那样是强迫让所有看代码的人都来看细节,不对 # -*- coding=utf-8 -*- from flask import Flask, make_response from helper import is_isbn_or_key app = Flask(__name__) app.config.from_object('con

iOS容易造成循环引用的三种场景NSTimer以及对应的使用方法(一)

NSTimer A timer provides a way to perform a delayed action or a periodic action. The timer waits until a certain time interval has elapsed and then fires, sending a specified message to a specified object(timer就是一个能在从现在开始的未来的某一个时刻又或者周期性的执行我们指定的方法的对象)

Block循环引用,强引用方法引起的循环引用,CenterX CenterY 不生效的问题

相信大家都用过CenterX 和 CenterY吧,这2个属性确实非常方便,但是有些时候会发现突然设置了CenterX CenterY不好使了,不居中了,一头雾水.这种情况 我建议第一时间去看看设置CenterX CenterY之前有没有设置size 也就是 宽和高.如果在设置宽高之前就设置了CenterX CenterY 肯定是不生效的,原因不用多说了吧,如果是这种情况,将先设置一下size就好了. 上一篇文章提到了block里面用了self从而导致了 循环引用,控制器释放不了,有些朋友知道应

shared_ptr造成的循环引用&amp;&amp;解决方法和原理(弱引用&amp;&amp;强引用)

 弱用指针的方式解决shared_ptr造成的循环引用防止内存泄漏! <***>循环引用就是由于智能指针shared_ptr造成的,下面就是shared_ptr的使用造成循环引用的图解: <****>举个例子来说下shared_ptr造成的循环引用: (选题背景双向链表) <span style="font-size:18px;">#include<memory> #include<iostream> using namesp

EntityFramework Model有外键时,Json提示循环引用 解决方法

正文之前先说两句,距离上篇博客已将近两个月,这方面的学习和探索并没有停止,而是前进道路上遇上了各种各样的问题,需要不断的整理.反思和优化,这段时间的成果,将在最近陆续整理发出来. 个人感觉国内心态太浮躁了,很少有能深入研究下去并将自己经验分享的人,可能很忙,也可能嫌麻烦.特别是面向新技术,尤其是在学习资料有限的情况下,愿意花费时间摸索和分享的人实在太少太少,遇到问题,搜索结果一抓一大把,但是往往都是转载,连最起码的自己验证都没有,结果就是以讹传讹,不仅对解决问题无用,反而容易产生误导.最近这段时

Python中循环引用(import)失败的解决方法

原文链接:http://blog.ihuxu.com/the-solution-to-the-problem-of-circular-import-in-python/ 我是采用方案三 "将引用放到函数内部"解决了这个问题.下面为原文. 前言 最近在开发智能家居项目hestia-rpi项目中,由于代码结构层级划分不合理,导致了循环引用(import)module失败的问题,错误如下: Traceback (most recent call last):  File "./ma

boost的shared_ptr循环引用

boost的智能指针给编程带来了极大的便利,不需要关心内存的释放,不要要调用delete,而且还可以定制delete的方法.其实boost的智能指针是可以当成scope_exit来用的,同样是退出时处理.但是凡事都是有利有弊,boost的shared_ptr如果在循环引用的时候会出现无法释放内存的情况,所谓循环引用就是A智能指针类里存放B的智能指针,B的智能指针类里存放A,将a.b的值互相设置.增加引用计数,在释放的时候由于计数问题,会导致在退出指针域的时候无法进行释放,解决该问题的方案是在类成

block的学习(block和timer的循环引用问题)

一.什么是回调函数? 回调函数,本质上也是个函数(搁置函数和方法的争议,就当这二者是一回事).由"声明"."实现"."调用"三部分组成. 在上面的例子中,我可以看出,函数amount(其实是Block),的声明和调用在A类中,而实现部分在B类中.也就是说,B类实现了amount函数,但并没有权限调用,最终还是 由A类触发调用.我们称这样的机制为"回调".意思是"虽然函数的实现写在B类中,但是真正的调用还是得由A类来完

小结OC中Retain cycle(循环引用)

retain cycle 的产生 说到retain cycle,首先要提一下Objective-C的内存管理机制. 作为C语言的超集,Objective-C延续了C语言中手动管理内存的方式,但是区别于C++的极其非人道的内存管理,Objective-C提出了一些机制来减少内存管理的难度. 比如:内存计数. 在 Objective-C中,凡是继承自NSObject的类都提供了两种方法,retain和release.当我们调用一个对象的retain时,这个 对象的内存计数加1,反之,当我们调用rel