从UITableViewController的视图模型呈现模态

时间:2018-12-07 11:26:38

标签: ios swift uitableview

我有一个UITableViewController,它是ViewModel类。我正在尝试使用 MVVM 模式构建应用程序。

我的tableView有一个显示图像的单元格,该图像具有一个手势识别器,该手势识别器在印刷时调用视图模型中的方法。

在这一点上,我想模态呈现一个ViewController,其中包含一些嵌入式内容。

但是我的TableView cell符合UITableViewCell,所以我不能从这里打电话。

我的ViewModel不符合任何条件,所以我也不能从那里调用present。

如何在UITableViewCell内触发模式出现?

2 个答案:

答案 0 :(得分:0)

您有几种选择,但我将与代表讨论解决方案。

这个想法是在protocol中定义该协议的MyViewModel和属性,并使MyViewController符合该协议。

MyViewModel的外观如下:

protocol MyViewModelDelegate: class {
    func didTapOnCell()
}

class MyViewModel {
    // Please note the delegate is weak and optional
    weak var delegate: MyViewModelDelegate?

    // This function handle gesture recognizer taps
    @objc func handleImageViewTap() {
        delegate?.didTapOnCell()
    }

    // Here is the rest of the ViewModel class...
}

然后在MyViewController中,将viewModel的委托属性设置为self并符合协议功能(我假设视图控制器引用了视图模型实例)。

class MyViewController: UITableViewController {

    func setup() {
        // ...
        // When MyViewModel is initialised, set the delegate property to self
        myViewModel.delegate = self
    }
}

extension MyViewController: ViewModelDelegate {
    func didTapOnCell() {
        // ...
        // Allocate instance of anotherViewController here and present it
        self.present(anotherViewController, animated: true, completion: .none)
    }
}

通过这种方式,您可以让MyViewController知道MyViewModel中发生的事情并采取相应的措施。

请注意,必须使delegate属性为可选属性,以避免保留周期。

答案 1 :(得分:0)

添加UIWindow扩展

扩展UIWindow {

static var top: UIViewController? {
    get {
        return topViewController()
    }
}

static var root: UIViewController? {
    get {
        return UIApplication.shared.delegate?.window??.rootViewController
    }
}

static func topViewController(from viewController: UIViewController? = UIWindow.root) -> UIViewController? {
    if let tabBarViewController = viewController as? UITabBarController {
        return topViewController(from: tabBarViewController.selectedViewController)
    } else if let navigationController = viewController as? UINavigationController {
        return topViewController(from: navigationController.visibleViewController)
    } else if let presentedViewController = viewController?.presentedViewController {
        return topViewController(from: presentedViewController)
    } else {
        return viewController
    }
}

}

比从任何地方都这样称呼:

    guard let topController = UIWindow.top else  { return } // UIWindow.root
    let youVC = theStoryboard.instantiateViewController(withIdentifier: "YourViewController") as! YourViewController
    youVC.modalTransitionStyle = .crossDissolve
    youVC.modalPresentationStyle = .overCurrentContext
    topController.present(youVC, animated: true, completion: nil)