内容简介:我们先来观察一个循环引用,如果想直接看结论的话可以点击:这里 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 写法》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Single Page Web Applications
Michael Mikowski、Josh Powell / Manning Publications / 2013-9-30 / USD 44.99
Code for most web sites mostly runs on the server. When a user clicks on a link, the site reacts slowly because the browser sends information to the server and the server sends it back again before di......一起来看看 《Single Page Web Applications》 这本书的介绍吧!
图片转BASE64编码
在线图片转Base64编码工具
RGB HSV 转换
RGB HSV 互转工具