Ios 避免简单操作的[弱自我]?
对于短时间运行的操作,是否可以避免Ios 避免简单操作的[弱自我]?,ios,swift,memory-management,urlsession,Ios,Swift,Memory Management,Urlsession,对于短时间运行的操作,是否可以避免[弱自我]?例如,URLSession将保留来自dataTask的闭包(带有:completion:): 在这种情况下,闭包会强烈地捕获self,这意味着即使闭包将此ViewController保存在内存中URLSession将保持关闭直到数据任务完成,这意味着ViewController的生命周期可能会延长到dataTask完成 在这种情况下,我们应该使用捕获列表来避免这种行为吗?我的推理正确吗,这里没有引用循环 ViewController的生命周期可能会延
[弱自我]
?例如,URLSession
将保留来自dataTask的闭包(带有:completion:)
:
在这种情况下,闭包会强烈地捕获self
,这意味着即使闭包将此ViewController
保存在内存中URLSession
将保持关闭直到数据任务完成,这意味着ViewController
的生命周期可能会延长到dataTask
完成
在这种情况下,我们应该使用捕获列表来避免这种行为吗?我的推理正确吗,这里没有引用循环
ViewController的生命周期可能会延长到dataTask完成
因此,问题是这是否是连贯的。这甚至可能是件好事。如果可以的话,那就好了,而且不需要弱自我
,因为没有保留周期,因为
url会话是共享的
但是当url会话是一个实例时
属性并有一个真正的委托,事情就复杂多了
您确实可以获得一个保留周期,因为会话保留其委托,而委托可能会保留会话 如果您担心引用周期,那么在使用URL请求时通常不会得到引用周期。问题是URL请求迟早会完成(几分钟后),并且您的控制器会被释放。引用循环只是临时的,不会导致内存泄漏 问题是,即使用户已经关闭了控制器,并且不再显示,您是否希望将控制器保留在内存中。这可能不会引起任何问题,但仍然是浪费。你持有的是你不需要的、不能重复使用的内存 还请注意,当控制器被解除时,您实际上可能希望取消正在运行的请求,以避免发送/接收不再需要的数据 在我看来,您不应该太担心引用周期,而应该更多地考虑所有权。强引用意味着拥有某个东西。请求没有理由“拥有”控制器。相反,控制器拥有并管理请求。如果没有所有权,我会使用
弱
,只是为了清楚起见
我的推理正确吗,这里没有引用循环
这里没有参考循环<代码>视图控制器未保留数据任务
完成处理程序。您可以将此视为iOS保留对视图控制器和完成处理程序的强引用,并且完成处理程序也保留对视图控制器的强引用。没有从视图控制器返回到完成处理程序的强引用,也没有到任何引用完成处理程序的对象链的强引用,因此您是无周期的。在UIView.animate
中查找相同的模式,在这里您再次向iOS发送闭包,而不是将它们存储在本地
对于短时间运行的操作,是否可以避免[弱自我]
工作的持续时间不是一个因素。这两个相关问题是:
class BadVC: UIViewController {
private lazy var cycleMaker: () -> Void = { print(self) }
override func loadView() {
view = UIView()
cycleMaker()
}
}
BadVC
在这里创建了一个引用循环,它在加载视图后将永远不会中断。cycleMaker()
将在纳秒内执行,这一事实并不能使我们免于内存泄漏
实际上,还有第三个问题:
class StillBadVC: UIViewController {
private lazy var cycleMaker: () -> Void = { print(self) }
override func loadView() {
view = UIView()
cycleMaker()
}
func breakCycle() {
cycleMaker = { }
}
}
在这里,我们处于危险之中,因为
StillBadVC
强烈引用了cycleMaker
,cycleMaker
捕获了对StillBadVC
的强烈引用。只要有人记得调用breakCycle()
,循环就会中断,此时视图控制器将删除对cycleMaker
的强引用,从而允许cycleMaker
解除分配。但是,如果有人忘记调用breakCycle()
,则循环不会中断。调用名为breakCycle()
的方法通常不是使用视图控制器合同的一部分,因此我们预计StillBadVC
在实践中会导致内存泄漏。我想您已经得到了答案。这不是一个参考周期
但要建立一个系统的方法,我的建议是一个更简单的方法。忘了考虑泄密之类的事情吧
考虑所有权和流量控制,然后考虑内存管理
- 所有权:此对象是否需要拥有此其他对象?对象是否应该拥有其委托?子视图应该拥有其父视图吗?此请求是否拥有此viewController
- 流控制:我要多久取消分配此对象?是立即还是在视图从屏幕上移除时
- 内存管理:这是一个强引用周期吗
这个思考过程不仅帮助您区分真正的内存泄漏和非泄漏。它还可以帮助您更好地设计和阅读代码,而不仅仅是盲目地到处乱扔
[脆弱的自我]
您肯定应该在这里使用[weak self]
,这不是因为存在强引用循环的任何风险,而是因为此闭包的存在只是为了更新标签。编写故意将视图控制器及其视图保留在内存中以便更新vi中的标签的代码是没有意义的
class StillBadVC: UIViewController {
private lazy var cycleMaker: () -> Void = { print(self) }
override func loadView() {
view = UIView()
cycleMaker()
}
func breakCycle() {
cycleMaker = { }
}
}