内容简介:我们先来观察一个循环引用,如果想直接看结论的话可以点击:这里 button 的点击回调里面会尝试 push 下一个控制器,这里还是很 OK 的,因为下一个控制器没有引用当前的控制器。所以我们给他添加一个引用。这里我们打印NxtViewController的
一个更优雅的 Swift Block 写法
我们先来观察一个循环引用,如果想直接看结论的话可以点击:
override func viewDidLoad() {
super.viewDidLoad()
button?.didTouchUpInsideBlock = { button in
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "NxtViewController") as! NxtViewController
self.present(vc, animated: true, completion: {
vc.dismiss(animated: true, completion: nil)
})
}
}
这里 button 的点击回调里面会尝试 push 下一个控制器,这里还是很 OK 的,因为下一个控制器没有引用当前的控制器。所以我们给他添加一个引用。
override func viewDidLoad() {
super.viewDidLoad()
button?.didTouchUpInsideBlock = { button in
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "NxtViewController") as! NxtViewController
vc.previousVC = self
self.present(vc, animated: true, completion: {
vc.dismiss(animated: true, completion: nil)
})
}
}
这里我们打印NxtViewController的 deinit 方法,会发现它已经不执行了,说明这时候已经不会销毁了。
循环引用有什么危害
有的人会说,循环引用会导致内存泄漏,是的没错,用户在不断操作过程中会不断生成NxtViewController但是不会释放,一个粒子是不断的进入下一个控制器,并返回,重复这个操作。这样会使得性能变差,导致很多问题。
当然我觉得循环引用会导致一些奇怪的问题才是最麻烦的,比如对于表格视图来说,循环引用可能会导致进入下一级的时候,下级页面还存有上次操作的数据。太可怕了!
打破循环引用
这个基本上是基础了,就是 [weak self]
,不仅如此,凡是会导致重复引用的都要使用 weak。像是这样:
[weak self, weak someParam]
,一旦使用 weak 修饰 self,那么下面使用的时候都需要把 self 看成可选值。
[unowned self]
这个的意思有点像是加了 !
,强制转换都是危险不安全的,非常不建议使用。
那么另外一个解决方法是,加 guard
操作符,比如:
button?.didTouchUpInsideBlock = { [weak self] _ in
guard let `self` = self else { return }
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "NxtViewController") as! NxtViewController
vc.previousVC = self
self?.present(vc, animated: true, completion: {
vc.dismiss(animated: true, completion: nil)
})
}
不过官方不建议这样做,参考 这里
其实这个操作只是利用了同名机制,我们可以改为:
button?.didTouchUpInsideBlock = { [weak self] _ in
guard let this = self else { return }
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "NxtViewController") as! NxtViewController
vc.previousVC = this
this.present(vc, animated: true, completion: {
vc.dismiss(animated: true, completion: nil)
})
}
这个操作是目前我比较喜欢的,调用起来像是在写 JS。
一个更优雅的解决方法
上面的操作有两个问题:
-
不管哪里用,我都要写这一句
[weak self] - 很容易忘写,其实这也是因为要写的地方太多
我们可以考虑在声明的时候就处理掉它,给 button 声明一个方法:
func setDidTouchUpInsideBlock<T: AnyObject>(to delegate: T, with block: @escaping (T, ExtendButton) -> ()) {
self.didTouchUpInsideBlock = {[weak delegate] button in
if let delegate = delegate {
block(delegate, button)
}
}
}
//我们就可以设置 button
button.setDidTouchUpInsideBlock(to: self) { (self, button) in
}
Done!
以上所述就是小编给大家介绍的《一个更优雅的 Swift Block 写法》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
设计原本
Frederick P. Brooks, Jr. / InfoQ中文站、王海鹏、高博 / 机械工业出版社 / 2011-1-1 / 55.00元
无论是软件开发、工程还是建筑,有效的设计都是工作的核心。《设计原本:计算机科学巨匠Frederick P. Brooks的思考》将对设计过程进行深入分析,揭示进行有效和优雅设计的方法。 本书包含了多个行业设计者的特别领悟。Frederick P. Brooks, Jr.精确发现了所有设计项目中内在的不变因素,揭示 了进行优秀设计的过程和模式。通过与几十位优秀设计者的对话,以及他自己在几个设计......一起来看看 《设计原本》 这本书的介绍吧!
JSON 在线解析
在线 JSON 格式化工具
图片转BASE64编码
在线图片转Base64编码工具