动态分配 ViewController 到 Navigate

Posted

技术标签:

【中文标题】动态分配 ViewController 到 Navigate【英文标题】:Dynamically assign ViewController to Navigate 【发布时间】:2020-05-07 07:24:09 【问题描述】:

就我而言,我有 UITableView 并有 查看全部 按钮,用于在单独的屏幕中列出所有项目。所以我在cellForRowAt 中添加了UIButton 操作方法的目标。现在我正在做的行动方法:

@IBAction func btnViewAllOffer(_ sender: UIButton) 
        let buttonPosition = sender.convert(CGPoint.zero, to: self.tblOfferView)
        let indexPath = self.tblOfferView.indexPathForRow(at: buttonPosition)

        if indexPath != nil 

            if let type = self.homeData[indexPath!.section].type 
                if type == HomeDataType.SponserProduct.rawValue 
                    let vc1 = self.storyboard?.instantiateViewController(withIdentifier: "ViewController1") as! ViewController1
                    if let title = self.homeData[indexPath!.section].title 
                        vc1.title = title
                    
                    self.navigationController?.pushViewController(vc1, animated: true)
                 else if type == HomeDataType.Offer.rawValue 
                    let vc2 = self.storyboard?.instantiateViewController(withIdentifier: "ViewController2") as! ViewController2
                    if let title = self.homeData[indexPath!.section].title 
                        vc2.title = title
                    
                    self.navigationController?.pushViewController(vc2, animated: true)
                 else if type == HomeDataType.BestSeller.rawValue 
                    let vc3 = self.storyboard?.instantiateViewController(withIdentifier: "ViewController3") as! ViewController3
                    if let title = self.homeData[indexPath!.section].title 
                        vc3.title = title
                    
                    self.navigationController?.pushViewController(vc3, animated: true)
                
            
        
    

我需要什么,有什么方法可以最小化代码并动态分配视图控制器,这样就不需要实例化每个视图控制器并每次推送它们? 比如:

var vc = UIViewController()
if let type = self.homeData[indexPath!.section].type 
    if type == HomeDataType.SponserProduct.rawValue 
        vc = ViewController1()
    
    else if type == HomeDataType.Offer.rawValue 
        vc = ViewController2()
     else if type == HomeDataType.BestSeller.rawValue 
        vc = ViewController3()
    

self.navigationController?.pushViewController(vc, animated: true)

【问题讨论】:

我更新了我的答案,以便更安全地处理 vcGeneric 可能未在任何 if/else 中初始化的情况 @denis_lor 我正在尝试你的代码 sn-ps 但它给了我错误 if let vcGeneric = vcGeneric if let title = self.homeData[indexPath!.section].title vcGeneric.strTitle = title self.navigationController?.pushViewController(vcGeneric, animated: true) 无法分配给属性:“vcGeneric”是一个“let”常量,无法将“SimilarViewController”类型的值转换为预期的参数类型“UIViewController” 你能用我答案中的更新代码试试吗? 【参考方案1】:

使用protocol (SimilarViewController) 来定义通用属性,如title

protocol SimilarViewController 
    var title: String?  get set 


class ViewController1: UIViewController, SimilarViewController 
    var title: String?

class ViewController2: UIViewController, SimilarViewController 
    var title: String?

class ViewController3: UIViewController, SimilarViewController 
    var title: String?



@IBAction func btnViewAllOffer(_ sender: UIButton) 
        let buttonPosition = sender.convert(CGPoint.zero, to: self.tblOfferView)
        let indexPath = self.tblOfferView.indexPathForRow(at: buttonPosition)

        if indexPath != nil 

            if let type = self.homeData[indexPath!.section].type 
                var vcGeneric: SimilarViewController?

                if type == HomeDataType.SponserProduct.rawValue 
                    vcGeneric = self.storyboard?.instantiateViewController(withIdentifier: "ViewController1") as! ViewController1
                 else if type == HomeDataType.Offer.rawValue 
                    vcGeneric = self.storyboard?.instantiateViewController(withIdentifier: "ViewController2") as! ViewController2
                 else if type == HomeDataType.BestSeller.rawValue 
                    vcGeneric = self.storyboard?.instantiateViewController(withIdentifier: "ViewController3") as! ViewController3
                


                if let title = self.homeData[indexPath!.section].title 
                    vcGeneric?.title = title
                

                if let vcGeneric = vcGeneric  as? UIViewController 
                    self.navigationController?.pushViewController(vcGeneric, animated: true)
                
            
        

【讨论】:

extension UIViewController: SimilarViewController 的目的是什么? @denis_lor 为什么你有 if else 在这里你不能使用在代码方面更具可读性的 switch case @TheCodeTalker 我留下的代码尽可能与原始代码相似,以便让提问的人了解问题出在哪里。重构是可能的,但我建议在问题解决后在范围之外进行 @denis_lor 是的,我注意到 exta let 但我从我的代码中删除了。 协议是一种方式。另一种方法是创建一个结构。我也更新了@Niraj_ios【参考方案2】:

1: 创建一个结构并为其赋值。

    struct TitleDetails  
         static var title : String = ""
    

2:创建viewController的扩展并使用它来避免代码重复。

    extension UIViewController 

        func pushVC(_ vcName : String) 
            let vc = UIStoryboard.init(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier: vcname)
            self.navigationController?.pushViewController(vc, animated: true)
        
    

3:现在你可以直接调用它了,

TitleDetails.title = yourTitleValue
self.pushVC("ViewController1")

在目标视图控制器的 ViewDidLoad() 方法中,

self.title = TitleDetails.title

【讨论】:

感谢@Keshu。但是如果我想传递数据呢? @Niraj_iOS 你只需要传递标题吗? 标题和数据模型数组。【参考方案3】:

创建 BaseViewController 并从 BaseViewController 派生其他 ViewController

class BaseViewController: UIViewController 
    var viewTitle = ""
    override func viewDidLoad() 
        super.viewDidLoad()
        // Do any additional setup after loading the view.

    

    func pushVC(_ vcName : String) 
        let vc = UIStoryboard.init(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier: vcName)

        self.navigationController?.pushViewController(vc, animated: true)
    

并在您需要的 ViewController 上使用以下代码:

@IBAction func btnViewAllOffer(_ sender: UIButton) 
        let buttonPosition = sender.convert(CGPoint.zero, to: self.tblOfferView)
        let indexPath = self.tblOfferView.indexPathForRow(at: buttonPosition)

        if indexPath != nil 

            if let type = self.homeData[indexPath!.section].type 
                self.viewTitle = self.homeData[indexPath!.section].title
                if type == HomeDataType.SponserProduct.rawValue 
                    self.pushVC("ViewController1")
                 else if type == HomeDataType.Offer.rawValue 
                    self.pushVC("ViewController2")
                 else if type == HomeDataType.BestSeller.rawValue 
                    self.pushVC("ViewController3")
                
            
        
    

【讨论】:

以上是关于动态分配 ViewController 到 Navigate的主要内容,如果未能解决你的问题,请参考以下文章

通过 JSON 动态创建 ViewController

用JavaScript声明分配给函数的多个变量的更好方法

ViewController 分配和释放问题

iOS Present Viewcontroller 出现黑屏

将 ViewController 分配给 Class,反之亦然

如何将 viewController 中的数据分配给 tableViewCell 标签?