【问题标题】:DataSource in separate class- cellForRowAt indexPath not called单独类中的数据源 - cellForRowAt indexPath 未调用
【发布时间】:2018-09-27 03:14:45
【问题描述】:

我想在一个单独的类中实现数据源。 我的实现似乎在这里工作

这是我的 UITableViewController

class MasterViewController: UITableViewController {

    @IBOutlet weak var itemsTableView: UITableView!
    let loginManager = LoginManager.shared
    let preferences = UserDefaultsManager.shared
    let appDelegate = UIApplication.shared.delegate
    var delegate: PreferencesDelegate?

    let apiClient = ApiClient.shared

    var timer:Timer?
    var count: Int = 10

    var items:[Item]? {
        didSet {
            let dataSource = ItemDataSource(items: items!)
            tableView.dataSource = dataSource
            tableView.reloadData()
            //itemsTableView.dataSource = self
            //itemsTableView.reloadData()
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        configureView()
    }

    func configureView() {
        self.navigationController?.navigationBar.topItem?.title = "You are logged in"
        apiClient.getData { (items) in
            DispatchQueue.main.async {
                self.items = items
                self.tableView.reloadData()
            }
        }
        DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
            //seconds delay before starting timer
            self.runTimer()
        }
    }

    func runTimer() {
        timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(MasterViewController.updateTimer)), userInfo: nil, repeats: true)
    }

    @objc func updateTimer() {
        if count > 0 {
            count -= 1
            self.navigationController?.navigationBar.topItem?.title = "session will expire in \(count) seconds"
        }

        if count == 0 {
            preferences.clear()
            pushToLoginVC()
            timer?.invalidate()
        }
    }


    func pushToLoginVC() {
        let navigationCoordinator = NavigationCoordinator(window: appDelegate!.window!!)
        navigationCoordinator.setRoot(id: "LoginVC")
        delegate?.getCurrentUser()
    }
}

这是 DataSource

class ItemDataSource: NSObject, UITableViewDataSource {


    private var items: [Item]
    init(items: [Item]) {
        self.items = items
        super.init()
    }


    // MARK: - Data Source
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return items.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        print("configure cell triggered")
        let itemCell = tableView.dequeueReusableCell(withIdentifier: "itemCell", for: indexPath) as! ItemViewCell

        let item = items[indexPath.row]
        let cellViewModel = ItemViewModel(item: item)
        itemCell.configure(viewModel: cellViewModel)

        return itemCell
    }

    // MARK: - Helper
    func item(at indexPath: IndexPath) -> Item {
        return items[indexPath.row]
    }
}

单元格标识符设置为“itemCell” 自定义类也设置为“ItemViewCell”

分配数据源。我用项目初始化数据源 我放了断点,我注意到 **cellForRowAt indexPath 从未被调用过。**

数据是从 json 文件中读取的。数组不为空。它已经过测试。 tableView.dataSource 不为零。该应用程序不会崩溃 主要问题是 cellForRowAt indexPath。我似乎想不通。我可以将所有数据源方法保留在同一个 MasterViewController 中,尽管我真的很想保留数据源方法以获得更好的代码质量,主要是在视图控制器变大时

有人知道吗?

【问题讨论】:

  • dataSource UITableView 的属性是 weak (weak var dataSource: UITableViewDataSource? { get set })。而你的是一个局部变量。它很快就会发布,这并不让我感到惊讶。在var delegate: PreferencesDelegate? 之后执行var dataSource: ItemDataSource? 并调用它然后dataSource = ItemDataSource(items: items!) 而不是let dataSource = ItemDataSource(items: items!)
  • 就像@Larme 所说,数据源对您的 didSet 具有本地范围。您可以将数据源设为 UITableViewController 的实例变量以保留它。
  • 非常感谢!!! :)

标签: swift uitableview tableview uitabbarcontroller datasource


【解决方案1】:

更新我的问题:

根据我收到的答案,我已添加 var dataSource:ItemDataSource 作为强参考。

如果dataSource是本地的,dataSource是弱的,不会被保留

class MasterViewController: UITableViewController {

    @IBOutlet weak var itemsTableView: UITableView!
    let loginManager = LoginManager.shared
    let preferences = UserDefaultsManager.shared
    let appDelegate = UIApplication.shared.delegate
    var delegate: PreferencesDelegate?

    let apiClient = ApiClient.shared

    var timer:Timer?
    var count: Int = 10
    **var dataSource:ItemDataSource?**

    var items:[Item]? {
        didSet {
            **dataSource = ItemDataSource(items: items!)**
            tableView.dataSource = dataSource
            tableView.reloadData()
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        configureView()
    }

    func configureView() {
        self.navigationController?.navigationBar.topItem?.title = "You are logged in"
        apiClient.getData { (items) in
            DispatchQueue.main.async {
                self.items = items
            }
        }
        DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
            //seconds delay before starting timer
            self.runTimer()
        }
    }

    func runTimer() {
        timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(MasterViewController.updateTimer)), userInfo: nil, repeats: true)
    }

    @objc func updateTimer() {
        if count > 0 {
            count -= 1
            self.navigationController?.navigationBar.topItem?.title = "session will expire in \(count) seconds"
        }

        if count == 0 {
            preferences.clear()
            pushToLoginVC()
            timer?.invalidate()
        }
    }


    func pushToLoginVC() {
        let navigationCoordinator = NavigationCoordinator(window: appDelegate!.window!!)
        navigationCoordinator.setRoot(id: "LoginVC")
        delegate?.getCurrentUser()
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-21
    相关资源
    最近更新 更多