首页 > 解决方案 > 更新超类的tableview

问题描述

我按照教程制作了一个 MVVP 模型表视图

我的 tableViewController 称为 MyProfileController,如下所示:

class MyProfileController: UITableViewController {

    fileprivate var viewModel: ProfileViewModel?
    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.register(UserInfoCell.self, forCellReuseIdentifier: UserInfoCell.identifier)
        viewModel = ProfileViewModel()
        tableView.dataSource = self.viewModel
        }
    }
}

我没有在 MyProfileController 中定义 UITableViewDataSource,而是创建了一个名为 ProfileViewModel 的视图模型并将其传递给tableView.dataSource. ProfileViewModel 的定义如下:

class ProfileViewModel: NSObject {
    fileprivate var profile: UserProfile?
    var items = [ProfileViewModelItem]()

    init() {
        super.init()
        //...
    }
}

extension ProfileViewModel: UITableViewDataSource {

    // ...

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! UserInfoCell
        cell.userDetailTextView.delegate = self
        return cell
    }

    // ...
}

extension ProfileViewModel: UITextViewDelegate {
    func textViewDidChange(_ textView: UITextView) {
        print(textView.text)

////////////////
// ERROR HERE //
//        tableView.beginUpdates()
//        tableView.endUpdates()
////////////////
    }
}

我在内部设置了 UITextView 的委托,cellForRowAt indexPath method以便textViewDidChange在用户在 textview 中键入时调用委托方法。到目前为止有效。问题是我无法从这里更新 tableView。如何更新 MyProfileController 的 tablView?

标签: iosswiftuitableview

解决方案


您可以使用闭包向您的表格视图控制器发送消息。

在数据源对象中声明一个闭包变量。

class ProfileViewModel: NSObject {

    var textViewDidChange: (() -> Void)?

    // If you need to send some data to your controller, declare it with type. In your case it's string.
    // var textViewDidChange: ((String) -> Void)?

}

将您的消息从您的文本字段委托发送到您新创建的变量,如下所示。

func textViewDidChange(_ textView: UITextView) {

    self.textViewDidChange?()
    // If you need to send your string, do it like this
    // self.textViewDidChange?(textView.text)

}

正如您可以猜到的,您的变量textViewDidChange仍然nil如此,因此不会有任何消息通过。所以我们现在应该宣布这一点。

在您可以访问数据源的视图控制器中,设置闭包的值。

class MyProfileController: UITableViewController {

    fileprivate var viewModel: ProfileViewModel?
    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.register(UserInfoCell.self, forCellReuseIdentifier: UserInfoCell.identifier)
        viewModel = ProfileViewModel()
        tableView.dataSource = self.viewModel

        // Set the closure value here

        viewmodel.textViewDidChange = { [unowned self](/* if you are sending data, capture it here, if not leave empty */) in

            // Do whatever you like with your table view here.
            // [unowned self] could sound tricky. It's whole another subject which isn't in the scope of this question. But of course there are some great answers here about it. Simply put, if you don't use it, you'll create a memory leak.

        }

    }

}

推荐阅读