jpatrick
jpatrick

Reputation: 43

Swift: pushed ViewController deinit not called

View Controller Structure

Main View Controller -> Table View Controller -> Detail View Controller

They are all embedded in Navigation Controller.

I pushed Detail View Controller by calling pushViewController. When I come back to Table View Controller from Detail View Controller, I realized Detail View Controller deinit() is not called, which causes fatal error at my project.

How can I make DetailViewController to deinit?? Thank you

Part of Table View Controller code where calls pushViewController

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        
        selectedTilId = thisDayTIL[indexPath.row].id
        
        if let detailVC = storyboard?.instantiateViewController(withIdentifier: "TILDetailViewController") as? TILDetailViewController {
            
            detailVC.tilId = selectedTilId
            detailVC.tilViewModel = self.tilViewModel
            detailVC.subjectViewModel = self.subjectViewModel
            
            self.navigationController?.pushViewController(detailVC, animated: true)
        }
        
    }

Whole Detail View Controller code

//
//  TILDetailViewController.swift
//

import UIKit
import RxSwift

class TILDetailViewController: UIViewController {
    
    @IBOutlet weak var tilTitleLabel: UILabel!
    @IBOutlet weak var tilSubjectLabel: UILabel!
    @IBOutlet weak var tilContentLabel: UILabel!
    
    var til: TIL!
    var tilId: Int!
    
    var tilViewModel: TILViewModel!
    var subjectViewModel: SubjectViewModel!
    
    var disposeBag = DisposeBag()
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        _ = tilViewModel.allTIL
            .map {
                $0.filter { $0.id == self.tilId }
            }
            .subscribe(onNext: { [weak self] til in
                self?.setLabelText(til[0])
                self?.til = til[0]
            })
            .disposed(by: disposeBag)
        
        let rightBarButton = UIBarButtonItem(title: "Edit", style: .plain, target: self, action: #selector(editButtonClicked))
        
        self.navigationItem.rightBarButtonItem = rightBarButton
    }
    
    deinit {
        print("DetailVC deinitialized")
    }
    
    @objc private func editButtonClicked(_ sender: Any) {
        guard let editVC = storyboard?.instantiateViewController(withIdentifier: "TILEditViewController") as? TILEditViewController else {
            return
        }
        editVC.til = til
        editVC.tilViewModel = self.tilViewModel
        editVC.subjectViewModel = self.subjectViewModel
        
        editVC.modalPresentationStyle = .overFullScreen
        self.present(editVC, animated: true, completion: nil)
    }
    
    func setLabelText(_ til: TIL) {
        tilTitleLabel.text = til.title
        tilContentLabel.text = til.content
        tilSubjectLabel.text = subjectViewModel.getSubjectNameById(til.subjectId)
    }
}

Upvotes: 2

Views: 2362

Answers (1)

Vadim Popov
Vadim Popov

Reputation: 1217

You're holding a strong reference to self in your Detailed VC which prevents it from being deallocated. This is called a retain cycle.

On this line: $0.filter { $0.id == self.tilId }.

Adding [weak self] to your map block will fix this.

Upvotes: 2

Related Questions