快速通用函数,可推送任何视图控制器



我正在尝试编写一个函数,该函数1(实例化UIViewController的子类,2(推送到调用方UIViewController的导航控制器。

到目前为止,我有这个:

func pushAnyViewController<T>(viewController:T, storyboardName:String) {
// Instantiate the view controller of type T
guard let nextViewController = UIStoryboard(name: storyboardName, bundle: nil).instantiateViewController(withIdentifier: String(describing: T.self)) as? T else {
return
}      

viewController.navigationController.pushViewController(nextViewController, animated: true)
}

这会产生错误

类型为"T"的值没有成员"导航控制器">

我不确定我是否应该以某种方式说T将永远是UIViewController的子类。如果是这样的话,不清楚我在哪里这样做。为此,我想到了:

func pushAnyViewController<T>(viewController:T & UIViewController, storyboardName:String)

但这会产生错误:

函数签名中不使用泛型参数"T">

非协议、非类类型"T"不能在协议约束类型中使用

您需要确定T是具有<T:UIViewController>的 vc

func pushAnyViewController<T:UIViewController>(viewController:T, storyboardName:String) {
guard let nextViewController = UIStoryboard(name: storyboardName, bundle: nil).instantiateViewController(withIdentifier: String(describing: T.self)) as? T else { return } 
viewController.navigationController?.pushViewController(nextViewController, animated: true)
}

最高答案不适合我,我需要一个更通用的解决方案。首先,我需要传递数据的选项,其次,我希望有一个可以推送或呈现VC的泛型函数,最后,我希望我的泛型函数可以从任何地方调用,而不仅仅是从UIViewController调用,这就是为什么UIViewController的扩展不适合我。

我决定使用简单的 init 和两个公共方法创建一个结构,以便我可以在任何地方创建副本并调用这些方法。

struct Navigator {

// MARK: - DisplayVCType enum
enum DisplayVCType {
case push
case present
}

// MARK: - Properties

private var viewController: UIViewController
static private let mainSBName = "Main"
// MARK: - Init
init(vc: UIViewController) {
self.viewController = vc
}

// MARK: - Public Methods

public func instantiateVC<T>(withDestinationViewControllerType vcType: T.Type,
andStoryboardName sbName: String = mainSBName) -> T? where T: UIViewController {
let storyBoard: UIStoryboard = UIStoryboard(name: sbName, bundle: nil)
let destinationVC = storyBoard.instantiateViewController(withIdentifier: String(describing: vcType.self))
return destinationVC as? T
}

public func goTo(viewController destinationVC: UIViewController,
withDisplayVCType type: DisplayVCType = .present,
andModalPresentationStyle style: UIModalPresentationStyle = .popover) {
switch type {
case .push:
viewController.navigationController?.pushViewController(destinationVC, animated: true)
case .present:
destinationVC.modalPresentationStyle = style
viewController.present(destinationVC, animated: true, completion: nil)
}
}
}

以及一些 VC 中的示例调用,在推送后传递字符串:

class SomeVC: UIViewController {
var navigator: Navigator?
override func viewDidLoad() {
super.viewDidLoad()
navigator = Navigator(vc: self)
}
func pushVC() {
guard let vc = navigator?.instantiateVC(withDestinationViewControllerType: VC1.self) else { return }
vc.someString = "SOME STRING TO BE PASSED"
navigator?.goTo(viewController: vc, withDisplayVCType: .push)
}

func presentVC() {
guard let vc = navigator?.instantiateVC(withDestinationViewControllerType: TableViewController.self) else { return }
navigator?.goTo(viewController: vc, withDisplayVCType: .present)
}
}

借助一些关键字。

enum Storyboard : String {
case Main
}
func viewController(_ viewController: UIViewController.Type) -> some UIViewController {
return UIStoryboard(name: self.rawValue, bundle: nil).instantiateViewController(withIdentifier: String(describing: viewController.self))
}

相关内容

最新更新