UIViewController没有释放,内存泄漏swift 4.0

时间:2018-05-16 14:05:11

标签: ios swift memory-leaks uiviewcontroller uinavigationcontroller

我有单一视图应用。 UINavigationViewController有一个根VC,里面有按钮。当pushVC从导航堆栈弹出时,它不会解除分配。 RootVC btnClick函数:

df=pd.DataFrame(columns=['a'])
df
Out[568]: 
Empty DataFrame
Columns: [a]
Index: []

df2=pd.DataFrame(columns=['b', 'c', 'd'])
pd.concat([df,df2])
Out[571]: 
Empty DataFrame
Columns: [a, b, c, d]
Index: []

pushVC有Notification Center订阅

@IBAction func btnClick(_ sender: Any) {
    let vc = pushVC.init()
    navigationController?.pushViewController(vc, animated: true)
}

log output:no deinit func called

class pushVC: UIViewController {


    override func viewDidLoad() {
        Log()

        //this line brokes dealloc after pop from navigation stack
        NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "event_name"), object: nil, queue: nil) { (notification) in
            self.printSomeText()
        }
    }

    deinit {
        Log()

    }

    func printSomeText() {
        Log()
    }
}


public func Log(filename: String = #file, line: Int = #line, funcname: String = #function) {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "HH:mm:ss:SSS"
    let file = filename.components(separatedBy: "/").last!
    print("[\(dateFormatter.string(from:Date())) \(file)(\(line)) \(funcname)] ->")
}

如果删除self.printSomeText(),则VC deinit按预期调用。

[16:50:44:321 pushVC.swift(16) viewDidLoad()] ->
[16:50:53:938 pushVC.swift(16) viewDidLoad()] ->
[16:56:52:909 pushVC.swift(16) viewDidLoad()] ->
[16:56:54:248 pushVC.swift(16) viewDidLoad()] ->
[16:56:55:655 pushVC.swift(16) viewDidLoad()] ->

self.printSomeText()行有什么问题? 它会保留自己吗?

1 个答案:

答案 0 :(得分:1)

更新您的addObserver以防止视图控制器自行保留...

override func viewDidLoad() {

    NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "event_name"), object: nil, queue: nil) { [weak self] notification in
        self?.printSomeText()
    }
}

你还应该让Notification.Name对其他对象可见,删除deinit上通知的观察者,并且最好拨打super.viewDidLoad() ...

extension NSNotification.Name {
    static let eventName = NSNotification.Name("event_name")
}

class pushVC: UIViewController {
    var observer: NSObjectProtocol?

    deinit {    
        if let observer = observer {
            NotificationCenter.default.removeObserver(observer)
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        observer = NotificationCenter.default.addObserver(forName: .eventName, object: nil, queue: nil) { [weak self] notification in
            self?.printSomeText()
        }
    }
}