问题
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