Search code examples
iosswiftuitableviewuisegmentedcontrolpass-data

cellForRowAt is not working in the childTableView


I am an entry-level swift developer and I am working in a personal application but I am having an issue in my "tableViewController".

I have a first tableview where I fetch some events from an API, and then what I am trying to do is to show a "detailViewController" whenever I Select an event. Until now everything seems perfect but my problem is my "detailsviewcontroller" has an image for the event, the title... and then an integrated "tableview" to show the details. At this point the numberOfRowsInSection function works but cellForRowAt never been called to fill the integrated tableview. Any help please? I hope I am being clear in my explanation

This is the code of the "childtableview" where I want to show the event details( I am using the array characters just to try:

import UIKit
import SwiftyJSON

class ChildDetailsViewController: UIViewController, UITableViewDelegate {
    var event: JSON?
    let detailsTableView = UITableView()
    var characters = ["test1", "test2", "test3", "test4"]
    override func loadView() {
        print("details")
       super.loadView()
       view.addSubview(detailsTableView)
       detailsTableView.translatesAutoresizingMaskIntoConstraints = false
       detailsTableView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
       detailsTableView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
       detailsTableView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
       detailsTableView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
       detailsTableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
       detailsTableView.dataSource = self
       detailsTableView.delegate = self
       detailsTableView.reloadData()
    }
}

extension ChildDetailsViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        //this insctruction does print 4 
        print(characters.count)
        //but it doesn't return 4 cells in the tableview
        return characters.count
  }

  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
    print(characters[indexPath.row])
    cell.textLabel?.text = characters[indexPath.row]
    return cell
  }
}

and here the code of the detailsViewController that contains the image and title and the child tableview:

import UIKit
import  SwiftyJSON

class EventDetailsViewController: UIViewController {
    var event : JSON?

    @IBOutlet weak var segmentedController: UISegmentedControl!
    @IBOutlet weak var ticketsView: UIView!
    @IBOutlet weak var locationView: UIView!
    @IBOutlet weak var detailsView: UIView!
    @IBOutlet weak var eventImage: UIImageView!
    @IBOutlet weak var eventTitle: UILabel!
    let newView = UIView()
    let childDetails = ChildDetailsViewController()
    var views : [UIView]!

    override func viewDidLoad() {
        filltheImageAndTile()
        // add new view to the main view
        super.viewDidLoad()
        view.addSubview(newView)

        //locate it under the event image and the segnented controller
        newView.translatesAutoresizingMaskIntoConstraints = false
        newView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        newView.topAnchor.constraint(equalTo: segmentedController.bottomAnchor, constant: 25).isActive = true
        newView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        newView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true

        views = [UIView]()
        views.append(ChildDetailsViewController().view)
        views.append(ChildLocationViewController().view)

        for itemView in views {
            newView.addSubview(itemView)
        }
        newView.bringSubviewToFront(ChildDetailsViewController().view)
    }

    @IBAction func segmentedControlOptionChanged(_ sender: UISegmentedControl) {
        newView.bringSubviewToFront(views[sender.selectedSegmentIndex])
    }

    @IBAction func backButtonClicked(_ sender: UIBarButtonItem) {
        self.navigationController?.dismiss(animated: true)
    }
}

Solution

  • The issue is you're creating an instance of ChildDetailsViewController and adding it's view to views array but ChildDetailsViewController's instance is never saved anywhere and never added it to parent view controller. and newView.bringSubviewToFront(ChildDetailsViewController().view) this line will do nothing cause you're creating a new instance and bringing its view to front but it's never been added to anywhere in super view

    views = [UIView]()
    views.append(ChildDetailsViewController().view)//this shouldn't be like this
    views.append(ChildLocationViewController().view)
    
    for itemView in views {
        newView.addSubview(itemView)
    }
    newView.bringSubviewToFront(ChildDetailsViewController().view)//this shouldn't be like this
    

    You've already created an instance childDetails you should use it like below

    childDetails.willMove(toParent: self)
    self.addChild(childDetails)
    
    let locationViewController = ChildLocationViewController()
    locationViewController.willMove(toParent: self)
    self.addChild(locationViewController)
    
    views = [UIView]()
    views.append(childDetails.view)
    views.append(locationViewController.view)
    
    for itemView in views {
        newView.addSubview(itemView)
    }
    childDetails.didMove(toParent: self)
    locationViewController.didMove(toParent: self)
    newView.bringSubviewToFront(childDetails.view)