c 如何避免循环引用用,有没有什么原则,准则之类的

Swift中的循环引用及weak使用 - 简书
<div class="fixed-btn note-fixed-download" data-toggle="popover" data-placement="left" data-html="true" data-trigger="hover" data-content=''>
写了19127字,被160人关注,获得了158个喜欢
Swift中的循环引用及weak使用
本文主要引用自
onevcat的文章
Mikael Konutgan的文章
本文针对需要做了部分截取或筛选,更多内容请看原文
什么是循环引用
Swift 是自动管理内存的,这也就是说,我们不再需要操心内存的申请和分配。当我们通过初始化创建一个对象时,Swift 会替我们管理和分配内存。而释放的原则遵循了自动引用计数 (ARC) 的规则:当一个对象没有引用的时候,其内存将会被自动回收。这套机制从很大程度上简化了我们的编码,我们只需要保证在合适的时候将引用置空 (比如超过作用域,或者手动设为 nil 等),就可以确保内存使用不出现问题。但是,所有的自动引用计数机制都有一个从理论上无法绕过的限制,那就是循环引用 (retain cycle) 的情况。假设我们有两个类 A 和 B, 它们之中分别有一个存储属性持有对方:
b.a = self
println("A deinit")
var a: A? = nil
println("B deinit")
在 A 的初始化方法中,我们生成了一个 B 的实例并将其存储在属性中。然后我们又将 A 的实例赋值给了 b.a。这样 a.b 和 b.a 将在初始化的时候形成一个引用循环。现在当有第三方的调用初始化了 A,然后即使立即将其释放,A 和 B 两个类实例的 deinit 方法也不会被调用,说明它们并没有被释放。
func application(application: UIApplication!, didFinishLaunchingWithOptions launchOptions: NSDictionary!)
// Override point for customization after application launch.
var obj: A? = A()
// 内存没有释放
return true
在 Swift 里防止循环引用
为了防止这种人神共愤的悲剧的发生,我们必须给编译器一点提示,表明我们不希望它们互相持有。一般来说我们习惯希望 "被动" 的一方不要去持有 "主动" 的一方。在这里 b.a 里对 A 的实例的持有是由 A 的方法设定的,我们在之后直接使用的也是 A 的实例,因此认为 b 是被动的一方。可以将上面的 class B 的声明改为:
weak var a: A? = nil
println("B deinit")
在 var a 前面加上了 weak,向编译器说明我们不希望持有 a。这时,当 obj 指向 nil 时,整个环境中就没有对 A 的这个实例的持有了,于是这个实例可以得到释放。接着,这个被释放的实例上对 b 的引用 a.b 也随着这次释放结束了作用域,所以 b 的引用也将归零,得到释放。添加 weak 后的输出:
总体说下来,我理解为在声明的时候,被动一方需要加上weak
其他一个例子
比如实现如下一个自定义控件
BlueSlider-480x94.png
定义整个控件为RangeSlider类
import UIKit
class RangeSlider: UIControl {
把这个控件的按钮定义为一个继承自CALayer的类,起名字叫RangeSliderThumbLayer,因为有两个,所以有
let lowerThumbLayer = RangeSliderThumbLayer()
let upperThumbLayer = RangeSliderThumbLayer()
更上边合成后RangeSlider类现在为这个样子
import UIKit
class RangeSlider: UIControl {
let lowerThumbLayer = RangeSliderThumbLayer()
let upperThumbLayer = RangeSliderThumbLayer()
那么RangeSliderThumbLayer应该是什么样子呢,如下:
import UIKit
import QuartzCore
class RangeSliderThumbLayer: CALayer {
weak var rangeSlider: RangeSlider?
在这里,rangeSlider引用回父 range slider。由于 RangeSlider 有两个 thumb layer,所以将这里的引用设置位 weak,避免循环引用。
那么此时在RangeSlider类中加入以下就不会出现问题了
lowerThumbLayer.rangeSlider = self
upperThumbLayer.rangeSlider = self
此时,RangeSliderThumbLayer是被动方,所以在其中写上weak
请我喝罐可乐就好$_$
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
被以下专题收入,发现更多相似内容:
心情不好的时候问自己 :
我为何这么屌
心情好的时候问自己 : 为什么比我屌的这么多
· 3801人关注
吸纳与swift有关的文章、教程、观点
· 688人关注
· 299人关注
请我喝罐可乐就好$_$
选择支付方式:序列化类型为“System.Globalization.CultureInfo”的对象时检测到循环引用。该如何避免
&来源:读书人网&【读书人网():综合教育门户网站】
序列化类型为“System.Globalization.CultureInfo”的对象时检测到循环引用。该如何处理//根据页码获得数据,
序列化类型为“System.Globalization.CultureInfo”的对象时检测到循环引用。该如何处理//根据页码获得数据,在()里要加上下文HttpContext context,要不然活不到数据 &
void GetPagedList(HttpContext context) &
//获取页码 &
string strPi = context.Request.QueryString[&pi&];
int intPi = 0; &
if (!int.TryParse(strPi, out intPi)) &
{[code=C#][/code] &
intPi = 1; &
BLL.GetDate dal = new BLL.GetDate(); &
DataSet list = dal.Bind();
//这行报错说“序列化类型为“System.Globalization.CultureInfo”的对象时检测到循环引用” &
string strJsonArr = new JavaScriptSerializer().Serialize(list); &
context.Response.Write(strJsonArr);
context.Response.End(); &
} &///////////////////////////////////////////////////////////////////////////////////////////////// &
public DataSet Bind() &
string sqlstr = &select * from board_info order by BoardId asc&; &
Common common = new Common(); &
DataSet ds=common.GetDataSet(sqlstr); & &
}[解决办法]不能序列化集合类吧。参数是object,只能序列对象之类的。网上有很多,把dataset转成JSON串的代码。用吧。查看: 16061|回复: 6
如何快速找到循环引用的位置 ?
阅读权限70
在线时间 小时
各位大侠,你们好!
有一个excel工作簿,里面有好几个工作表,经常会出现一个对话框,提示循环引用问题,但不知道是哪个单元格出现了循环引用,因为有好几个工作表,请哪位大侠帮忙指点一下,有什么办法可以快速找到循环引用的单元格,谢谢!
阅读权限70
在线时间 小时
有没有哪位知道?
请帮忙指点一下。
阅读权限95
在线时间 小时
如果有循环引用,状态栏就会显示。如果循环引用不在本工作表,显示“循环”,如果是在本工作表,显示“循环: XX(某某单元格坐标)。
阅读权限95
在线时间 小时
还可以用循环引用工具栏。
视图-工具栏-循环引用
阅读权限70
在线时间 小时
我试试,谢谢!
阅读权限30
在线时间 小时
学习了,谢谢
阅读权限20
在线时间 小时
感谢“交叉点”。在你的提示下我在2013版找到的路径。
供用2013版的朋友参考:公式---错误检查---循环引用
玩命加载中,请稍候
玩命加载中,请稍候
Powered by
本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任! & & 本站特聘法律顾问:徐怀玉律师 李志群律师

我要回帖

更多关于 会计准则收入确认原则 的文章

 

随机推荐