How to make viewDidLoad method of ViewController call only once?

老子叫甜甜 提交于 2020-01-03 02:55:11

问题


I created a Container View in my application. The container view loads other UIViewController when user tabs on a UITableviewCell and other UIViewController gets loaded inside the Container View. I tried testing by inserting log messages on other ViewController class and found out each time viewDidLoad and ViewDidAppear method gets called which states those class gets instantiated everytime on cell tab.

But while studying about container view on the apple docs https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/CreatingCustomContainerViewControllers/CreatingCustomContainerViewControllers.html

I found UITabBarController also implements ContainerView and manages its UIViewController in array. I tried inspecting the log messages and found that viewDidLoad method gets called only one time and when we visit second time on the tab only viewDidAppear gets called. So i was really wondering what is the behind the scene things in this. Are they using UnWind segue(i guess not).

However i created container View Controller with follwing way following these tutorial: https://github.com/codepath/ios_guides/wiki/Container-View-Controllers-Quickstart as

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")


        }




    }


}

回答1:


The tab bar controller has an array of child controllers which persist when switching between them.

Basically what you need to do is:

  • create a container to hold the child controllers (an array)
  • add controller to the array if it does not exist
  • reuse the controller from the array if it exists

I use this procedure in quite a few places.

Note this also works great with having navigation controllers in the content view but the navigation stack will persist as well which may not be a desired result. For instance if you have 3 tabs and the 1st tab is navigated to 2nd view controller it will stay on 2nd view controller even after switching to 3rd tab and back to the 1st one.




回答2:


Cache the inactive view controllers in an array after being allocated, and you'll call their viewDidLoad method only once.

Right now viewDidLoad is called because you're allocating a new view controller each time.



来源:https://stackoverflow.com/questions/29699001/how-to-make-viewdidload-method-of-viewcontroller-call-only-once

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!