如何让 ViewController 的 viewDidLoad 方法只调用一次?

How to make viewDidLoad method of ViewController call only once?

我在我的应用程序中创建了一个 容器视图。当用户点击 UITableviewCell 和其他 UIViewController 时,容器视图会加载其他 UIViewController 被加载到容器视图中。我尝试通过在其他 ViewController class 上插入日志消息来进行测试,每次都发现 viewDidLoadViewDidAppear 方法被调用,它指出那些 class 每次都在单元格选项卡上被实例化。

但是在苹果文档上研究容器视图时 https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/CreatingCustomContainerViewControllers/CreatingCustomContainerViewControllers.html

我发现 UITabBarController 也实现了 ContainerView 并在数组中管理它的 UIViewController。我尝试检查日志消息,发现 viewDidLoad 方法仅被调用一次,而当我们第二次访问选项卡时仅被调用 viewDidAppear 被调用。所以我真的很想知道这幕后的事情是什么。他们是否在使用 UnWind segue(我猜不是)。

但是我按照这些教程使用以下方式创建了容器 View Controller: https://github.com/codepath/ios_guides/wiki/Container-View-Controllers-Quickstart 作为

class ViewController: UIViewController {


    @IBOutlet weak var contentView: UIView!

    var activeViewController : UIViewController? {
        didSet{
            removeInactiveViewController(oldValue)
            updateActiveViewController()
        }
    }


    var cellTxtArrs = ["FIRST","SECOND","THIRD"]

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        var tblView : UITableView = UITableView()
        tblView.frame = CGRectMake(0, 20, 300 ,100)
        tblView.separatorColor = UIColor.clearColor()
        tblView.scrollEnabled = false
        tblView.rowHeight = (30)
        self.view.addSubview(tblView)
        tblView.delegate = self
        tblView.dataSource = self
        tblView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "myCell")


    }



    func removeInactiveViewController(inactiveViewController:UIViewController?){


        if let inActiveVC = inactiveViewController{

            inActiveVC.willMoveToParentViewController(nil)

            inActiveVC.view.removeFromSuperview()

            inActiveVC.removeFromParentViewController()

        }


    }


    func updateActiveViewController(){


        if let activeVC = activeViewController{

            //not necessary
            addChildViewController(activeVC)

            activeVC.view.frame = contentView.bounds

            contentView.addSubview(activeVC.view)

            activeVC.didMoveToParentViewController(self)




        }


    }





    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}


extension ViewController : UITableViewDataSource , UITableViewDelegate{

    //MARK:  table view data source methods
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

        //  cell.textLabel?.font = UIFont(name: label.font.fontName, size: 22)
        var cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier("myCell") as! UITableViewCell
        cell.backgroundColor = UIColor(red: 0.000, green: 0.400, blue: 0.404, alpha: 1.00)
        cell.selectionStyle =  UITableViewCellSelectionStyle.None
        cell.textLabel?.text = self.cellTxtArrs[indexPath.row]
        cell.textLabel?.textAlignment = NSTextAlignment.Left
        cell.textLabel?.textColor = UIColor.whiteColor()

        return cell

    }

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return self.cellTxtArrs.count

    }


    //MARK: - table view delegate methods

    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

        var row = indexPath.row

        switch row {

        case 0:




                let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
                let firstVC = storyboard.instantiateViewControllerWithIdentifier("firstVC") as! FirstViewController
                activeViewController = firstVC



        case 1:

                var storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
                let secondVC = storyboard.instantiateViewControllerWithIdentifier("secondVC") as! SecondViewController
                activeViewController = secondVC


        case 2:


                let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
                let thirdVC = storyboard.instantiateViewControllerWithIdentifier("thirdVC") as! ThirdViewController
                activeViewController = thirdVC



        default:
            println("no index")


        }




    }


}

选项卡栏控制器有一个子控制器数组,在它们之间切换时这些子控制器仍然存在。

基本上你需要做的是:

  • 创建一个容器来容纳子控制器(一个数组)
  • 如果控制器不存在则添加控制器到数组
  • 重新使用数组中的控制器(如果存在)

我在很多地方都使用了这个程序。

请注意,这也适用于在内容视图中使用导航控制器,但导航堆栈也会持续存在,这可能不是理想的结果。例如,如果您有 3 个选项卡,并且第一个选项卡导航到第二个视图控制器,即使在切换到第三个选项卡并返回到第一个选项卡后,它仍将保留在第二个视图控制器上。

在分配后将非活动视图控制器缓存在一个数组中,您将只调用它们的 viewDidLoad 方法一次。

现在调用了 viewDidLoad,因为您每次都在分配一个新的视图控制器。