如何让 ViewController 的 viewDidLoad 方法只调用一次?
How to make viewDidLoad method of ViewController call only once?
我在我的应用程序中创建了一个 容器视图。当用户点击 UITableviewCell 和其他 UIViewController 时,容器视图会加载其他 UIViewController 被加载到容器视图中。我尝试通过在其他 ViewController class 上插入日志消息来进行测试,每次都发现 viewDidLoad 和 ViewDidAppear 方法被调用,它指出那些 class 每次都在单元格选项卡上被实例化。
我发现 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,因为您每次都在分配一个新的视图控制器。
我在我的应用程序中创建了一个 容器视图。当用户点击 UITableviewCell 和其他 UIViewController 时,容器视图会加载其他 UIViewController 被加载到容器视图中。我尝试通过在其他 ViewController class 上插入日志消息来进行测试,每次都发现 viewDidLoad 和 ViewDidAppear 方法被调用,它指出那些 class 每次都在单元格选项卡上被实例化。
我发现 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,因为您每次都在分配一个新的视图控制器。