【问题标题】:Dynamically assign ViewController to Navigate动态分配 ViewController 到 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”
  • 你能用我答案中的更新代码试试吗?

标签: ios swift navigation


【解决方案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")
                }
            }
        }
    }

【讨论】:

    猜你喜欢
    • 2011-01-06
    • 2010-12-04
    • 2020-12-05
    • 1970-01-01
    • 2019-06-25
    • 1970-01-01
    • 1970-01-01
    • 2015-08-21
    • 1970-01-01
    相关资源
    最近更新 更多