我有一个UITableViewController
,它是ViewModel类。我正在尝试使用 MVVM 模式构建应用程序。
我的tableView有一个显示图像的单元格,该图像具有一个手势识别器,该手势识别器在印刷时调用视图模型中的方法。
在这一点上,我想模态呈现一个ViewController
,其中包含一些嵌入式内容。
但是我的TableView cell
符合UITableViewCell
,所以我不能从这里打电话。
我的ViewModel不符合任何条件,所以我也不能从那里调用present。
如何在UITableViewCell
内触发模式出现?
答案 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)