Reputation: 215
I want to display a UITableView
inside a UIViewController
. This View Controller contains a UISegmentedControl
with two screens (FirstViewController
and SecondViewController
).
The first View Controller is the one that contains the UIViewTable
(please don't mind the second).
When I execute the app in the simulator, everything works fine, but when I try to scroll the table view in the first ViewController, the cells disappear. The only way to make them reappear is to kill the app and reopen it again.
I'm new to iOS development (I come from Android), and I'm obviously missing something here.
I already tried adding a UIViewTable
outside a container UIView
and it works fine. So I'm guessing the problem has to do with the container or the segmented control...
Here's my implementation:
UIViewController
with UISegmentedControl
and UIView
(which will contain the two screens of the segmented control).
View Controller
@IBOutlet weak var container: UIView!
var sectionViews:[UIView]!
override func viewDidLoad() {
super.viewDidLoad()
sectionViews = [UIView]()
sectionViews.append(FirstViewController().view)
sectionViews.append(SecondViewController().view)
for v in sectionViews {
container.addSubview(v)
}
container.bringSubviewToFront(sectionViews[0])
}
@IBAction func switchViewsAction(_ sender: UISegmentedControl) {
self.container.bringSubviewToFront(self.sectionViews[sender.selectedSegmentIndex])
}
First View Controller
The FirstViewController
has a swift
and a xib
files, and has two files Cell.swift
and Cell.xib
for the table cell.
FirstViewController.swift
@IBOutlet weak var tableView: UITableView!
let cellID = "CellId"
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.register(UINib(nibName: "Cell", bundle: nil), forCellReuseIdentifier: cellID)
self.tableView.dataSource = self
self.tableView.delegate = self
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 100
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCell(withIdentifier: cellID, for: indexPath) as! Cell
cell.label.text = "\(indexPath.row)"
return cell
}
FirstViewController.xib
Cell.xib
Any help will be appreciated! Thanks
Upvotes: 2
Views: 1825
Reputation: 767
import UIKit
class TestViewController: UIViewController , UITableViewDataSource, UITableViewDelegate{
@IBOutlet weak var segmentControlOutlet: UISegmentedControl!
@IBOutlet weak var tableView: UITableView!
var arrayName = ["Label1", "Label2", "Label3","Label4","Label5","Label6","Label7","Label8","Label9","Label10"]
var arrayName2 = ["Label1", "Label2", "Label3","Label4","Label5"]
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
@IBAction func segmentControlAction(_ sender: UISegmentedControl) {
self.tableView.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if segmentControlOutlet.selectedSegmentIndex == 0 {
return arrayName.count
}else{
return arrayName2.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TestTableViewCell", for: indexPath) as! TestTableViewCell
if segmentControlOutlet.selectedSegmentIndex == 0 {
cell.textLabel?.text = arrayName[indexPath.row]
}else{
cell.textLabel?.text = arrayName2[indexPath.row]
}
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 50
}
}
And this code is for UITableViewCell Class:-
import UIKit
class TestTableViewCell: UITableViewCell {
@IBOutlet weak var labelName: UILabel!
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
}
}
Upvotes: 0
Reputation: 534925
One obvious problem is that you are saying container.addSubview(v)
without giving v
any frame or constraints. Since you use autolayout to position container
, you ought to use autolayout to position v
as well. You should set its top, bottom, leading, and trailing anchors to equal those of container
with a constant
of zero. (And set its translates...
to false
.) Do that for both cases of v
in the loop.
However, there is much more serious problem, which is that the view controllers that you create by saying FirstViewController()
and SecondViewController()
are not retained. Therefore they vanish in a puff of smoke. They thus lose their functionality; for example, the table view no longer has any data source or delegate so it has no cells.
What you are doing is totally illegal. You cannot simply use a view controller to "dumpster-dive" as a way of grabbing its view and shove its view, willy-nilly, into the interface. You must make the view controller a child view controller of your parent view controller (Item in this case). There is an elaborate dance you must do in order to ensure that the child view controller has its proper place in the view controller hierarchy and receives in good order all the messages that a view controller must receive, and you are not doing the dance.
For examples of how to do the dance, see for instance my answers
and
Upvotes: 2