我对iOS的内存泄漏和性能问题感到非常兴奋。目前我已经了解到通过保留周期避免泄漏。我在下面有一个片段,其中包含两个viewcontrollers,我正在通过委托传递数据。但是当我将委托var均衡为nil时,没有调用viewcontroller的deinit。
import UIKit
class ViewController: UIViewController, Navigator {
func passData(data: String) {
print("Passed data: " + data)
}
override func viewDidLoad() {
super.viewDidLoad()
}
deinit {
print("deinited: " + self.description)
}
@IBAction func goSecond(_ sender: UIButton) {
let secondVC = self.storyboard?.instantiateViewController(withIdentifier: "secondVC") as! SecondVC
secondVC.delegate = self
self.present(secondVC, animated: false, completion: nil)
}
}
// second vc
import UIKit
protocol Navigator: class{
func passData(data:String)
}
class SecondVC: UIViewController {
weak var delegate:Navigator?
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func GoFirst(_ sender: UIButton) {
delegate?.passData(data: "I'm second VC and Passing")
self.delegate = nil
}
}
答案 0 :(得分:3)
您误解了deinit
方法的工作。当视图控制器的实例没有任何引用时,应该调用deinit。因此,只是删除视图控制器属性的引用并不能完成整个工作。
你误以为self.delegate = nil
中有SecondVC
。这应该在您的第一个ViewController
。
为了理解一切,我做了一个示例项目,你可以在那里学习如何工作。主要代码在这里:
第一视图控制器
class FirstViewController: UIViewController, Navigator {
override func viewDidLoad() {
super.viewDidLoad()
}
deinit {
print("First view controller's deinit called")
}
func passData(data: String) {
print("In First view controller: \(data)")
}
@IBAction func gotoSecond(_ sender: UIButton) {
let viewcontroller = storyboard?.instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController
viewcontroller.delegate = self
show(viewcontroller, sender: self)
}
}
第二视图控制器
protocol Navigator {
func passData(data:String)
}
class SecondViewController: UIViewController {
weak var delegate:Navigator?
override func viewDidLoad() {
super.viewDidLoad()
}
deinit {
print("Second view controller's deinit called")
}
@IBAction func closeButton(_ sender: UIButton) {
delegate?.passData(data: "Delegation from second view controller")
dismiss(animated: true, completion: nil) //when this line executes, the instance of this class is de-referenced. This makes the call to deinit method of this class.
}
}
因此,当第二个视图控制器发生dismiss
时,第二个视图控制器的引用计数转到0
,这样就可以调用第二个视图控制器的deinit
方法。
但从技术上讲,您不会调用第一个视图的
deinit
控制器,因为您实际上没有取消引用第一个视图 控制器。
您可以找到整个项目here。