简体   繁体   中英

Table view cells not loading in view controller

Swift As you can see in this swift code I am trying to create a table view for my logout controller. However, I am facing problems with the "log out" button showing as a cell in my view controller. I don't know what the problem is because it builds without any errors and I have gone and checked several times but can't find the problem.

import UIKit

struct SettingsCellModel {
    let title: String
    let handler: (() -> Void)
}

 final class SettingsViewController: UIViewController {
    
        private var tableView: UITableView {
        let tableView = UITableView(frame: .zero, style: .grouped)
            tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
        return tableView
        }
    
    private var data = [[SettingsCellModel]]()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        configureModels()
        view.backgroundColor = .systemBackground
        view.addSubview(tableView)
        tableView.delegate = self
        tableView.dataSource = self
        // Do any additional setup after loading the view.
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        tableView.frame = view.bounds
    }
    private func configureModels() {
       
        let section = [SettingsCellModel(title: "Log Out") { [weak self] in
            self?.didTapLogOutButton()
        }
        ]
        data.append(section)
    }
    private func didTapLogOutButton() {
        
        let actionSheet = UIAlertController(title: "Log Out", message: "Are you sure you want to log out", preferredStyle: .actionSheet)
        actionSheet.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
        actionSheet.addAction(UIAlertAction(title: "Log Out", style: .destructive, handler: { _ in
           logOut (completion: { success in
                DispatchQueue.main.async {
                    if success {
                        //present log in
                        let loginVC = LoginViewController()
                        loginVC.modalPresentationStyle = .fullScreen
                        self.present(loginVC, animated: true) {
                        self.navigationController?.popToRootViewController(animated: false)
                        self.tabBarController?.selectedIndex = 0
                    }
                    }
                    else {
                        //error occurred
                        fatalError("Could not log out user")
                    }
                }
            })
        }))
        actionSheet.popoverPresentationController?.sourceView = tableView
        actionSheet.popoverPresentationController?.sourceRect = tableView.bounds
        
        present(actionSheet, animated: true)
        
    }
}
extension SettingsViewController: UITableViewDelegate, UITableViewDataSource {
    func numberOfSections(in tableView: UITableView) -> Int {
        return data.count
        
    }
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return data[section].count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        cell.textLabel?.text = data[indexPath.section][indexPath.row].title
        
        return cell
        
    }
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        data[indexPath.section][indexPath.row].handler()
    }
}

Issue is you are using Computed property private var tableView: UITableView { that means every time you access tableView in your code its closure is executed (or its value is evaluated), and because you instantiate a new instance of tableView in its closure you receive different instances of tableView in all the 3 statements

        view.addSubview(tableView)
        tableView.delegate = self
        tableView.dataSource = self

hence tableView instance you added as subView is different from the one that has delegate and data source set as self.

What you need

Option 1:

    private var tableView: UITableView = {
        let tableView = UITableView(frame: .zero, style: .grouped)
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
        return tableView
    }()

Option 2: (Preferred)

    private lazy var tableView: UITableView = {
        let tableView = UITableView(frame: .zero, style: .grouped)
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
        return tableView
    }()

Hope it helps

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM