swiftuitableviewuiviewcontrollerstoryboardsubview

Table Content disappears on Scroll in TableView with Custom Cell using Subview - Swift


I have a ViewController which uses multiple Subviews (HomeViewController, etc.) which can be selected via a Custom Tab Bar at the bottom of my app. Inside the HomeViewController there is a UIView containing a UITableView containing a Prototype Custom Cell with name and image.

import UIKit

class HomeViewController: UIViewController {

@IBOutlet weak var friendView: UITableView!

let friends = ["batman", "harsh", "ava", "sasha", "fatima", "alfred"]

override func viewDidLoad() {
    super.viewDidLoad()
    friendView.delegate = self
    friendView.dataSource = self
    friendView.allowsSelection = false
}
}

extension HomeViewController: UITableViewDelegate, UITableViewDataSource {

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return 120
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return friends.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = friendView.dequeueReusableCell(withIdentifier: "customCell") as! CustomCell
    let friend = friends[indexPath.row]
    cell.avatarImg.image = UIImage(named: friend)
    cell.nameLbl.text = friend
    return cell
}
}

Custom cell:

import UIKit

class CustomCell: UITableViewCell {

@IBOutlet weak var friendView: UIView!
@IBOutlet weak var nameLbl: UILabel!
@IBOutlet weak var avatarImg: UIImageView!

override func awakeFromNib() {
    super.awakeFromNib()
    // Initialization code
}

override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

    // Configure the view for the selected state
}
}

When I start the app, everything looks just fine. However, when I start scrolling inside the table, all data suddenly disappears. All relations between storyboard and code should be just fine. I think it might have got something to do with my need of using a Subview.

import UIKit

class ViewController: UIViewController {

@IBOutlet weak var tabBarView: UIView!
@IBOutlet weak var contentView: UIView!

override func viewDidLoad() {
    super.viewDidLoad()
    
    Design.makeCornersRound(view: tabBarView, radius: 10.0)
    
    Timer.scheduledTimer(withTimeInterval: 0.1, repeats: false) { (timer) in
        self.switchToHomeViewController()
    }
}

@IBAction func onClickTabBar(_ sender: UIButton) {
    let tag = sender.tag
    
    if tag == 1 {
        switchToIncomingsViewController()
    }
    else if tag == 2 {
        switchToSpendingsViewController()
    }
    else if tag == 3 {
        switchToHomeViewController()
    }
    else if tag == 4 {
        switchToSavingsViewController()
    }
    else if tag == 5 {
        switchToSettingsViewController()
    }
}

func switchToHomeViewController() {
    guard let Home = self.storyboard?.instantiateViewController(withIdentifier: "HomeViewController") as? HomeViewController else { return }
    contentView.addSubview(Home.view)
    Home.didMove(toParent: self)
}
...
}

Reference to the tutorial I have been trying to implement: https://www.youtube.com/watch?v=ON3Z0PXSoVk


Solution

  • In this function:

    func switchToHomeViewController() {
        // 1
        guard let Home = self.storyboard?.instantiateViewController(withIdentifier: "HomeViewController") as? HomeViewController else { return }
        // 2
        contentView.addSubview(Home.view)
        // 3
        Home.didMove(toParent: self)
        // 4
    }
    

    You need to add the controller as a child controller.

    As a side note, use lowerCase for variable names:

    func switchToHomeViewController() {
        // create an instance of HomeViewController
        guard let homeVC = self.storyboard?.instantiateViewController(withIdentifier: "HomeViewController") as? HomeViewController else { return }
        // add it as a child view controller
        self.addChild(homeVC)
        // add its view
        contentView.addSubview(homeVC.view)
        // here you should either set the view's frame or add constraints
        //  such as:
        homeVC.view.frame = contentView.bounds
        // inform the controller that it moved to a parent controller
        homeVC.didMove(toParent: self)
    }