I'm creating an iOS app using swift. I want to build a non scrollable tableView which shows on screen all informations contained in datasource, so the height of each cell depends on the number of entries in data. For example, if the height of the view is 500 and data.count = 10, each cell's height is 50. A problem appears when the cell's height is ~100.8 (corresponding to 5 entries in my data, using my iPhone 5). In fact, even by setting tableView.separatorStyle = .None , a weird separator appears for this cell's height.
Below, the first image (7 entries in data) is normal and on the second (5 entries in data) those separators appear.
Here is my view controller :
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
let reuseIdentifier = "Cell"
var data = ["bobby", "bob", "john", "helena", "clara", "oliver", "steve"]
var visibleHeight:CGFloat!
override func viewDidLoad() {
super.viewDidLoad()
edgesForExtendedLayout = .None
tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: reuseIdentifier)
editModeOff()
tableView.scrollEnabled = false
visibleHeight = viewVisibleSize.height
tableView.separatorStyle = .None
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return data.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCellWithIdentifier(reuseIdentifier, forIndexPath: indexPath)
cell.textLabel!.text = data[indexPath.row]
cell.selectionStyle = .None
return cell
}
func tableView(tableView: UITableView, moveRowAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath) {
let stringToMove = data[sourceIndexPath.row]
data.removeAtIndex(sourceIndexPath.row)
data.insert(stringToMove, atIndex: destinationIndexPath.row)
}
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete{
data.removeAtIndex(indexPath.row)
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Fade)
}
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
print(visibleHeight/CGFloat(data.count))
return visibleHeight/CGFloat(data.count)
}
func editModeOn(){
tableView.setEditing(true, animated: true)
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .Done, target: self, action: "editModeOff")
}
func editModeOff(){
tableView.setEditing(false, animated: true)
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .Edit, target: self, action: "editModeOn")
}
}
extension ViewController{
var viewVisibleSize:CGSize{
var size = view.bounds.size
if !UIApplication.sharedApplication().statusBarHidden{
size.height -= UIApplication.sharedApplication().statusBarFrame.height
}
if let navigationController = navigationController{
size.height -= navigationController.navigationBar.bounds.height
}
if let tabBarController = tabBarController{
size.height -= tabBarController.tabBar.bounds.height
}
return size
}
}
I always clear the color of the separator:
tableView.separatorColor = UIColor.clearColor()
I have found a dirty solution by setting :
cell.contentView.layer.borderWidth = 0.5
cell.contentView.layer.borderColor = UIColor.whiteColor().CGColor
in tableView:cellForRowAtIndexPath: method. But for sure, there is a better way...
In your viewDidLoad: you can try self.tableView.tableFooterView = UIView()
It is funny. Problem in your function tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
It has strange behavior for some float numbers and a separator will appear.
I offer you round a returning height like this:
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
print(self.visibleHeight/CGFloat(self.tableArray.count))
let rett = self.visibleHeight/CGFloat(self.tableArray.count)
let convert = NSString(format: "%.0f", rett)
return CGFloat(convert.floatValue)
}
Related
I'm able to expand and collapse cells but i wanna call functions (expand and collapse) inside UITableViewCell to change button title.
import UIKit
class MyTicketsTableViewController: UITableViewController {
var selectedIndexPath: NSIndexPath?
var extraHeight: CGFloat = 100
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! MyTicketsTableViewCell
return cell
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if(selectedIndexPath != nil && indexPath.compare(selectedIndexPath!) == NSComparisonResult.OrderedSame) {
return 230 + extraHeight
}
return 230.0
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if(selectedIndexPath == indexPath) {
selectedIndexPath = nil
} else {
selectedIndexPath = indexPath
}
tableView.beginUpdates()
tableView.endUpdates()
}
}
import UIKit
class MyTicketsTableViewCell: UITableViewCell {
#IBOutlet weak var expandButton: ExpandButton!
#IBOutlet weak var detailsHeightConstraint: NSLayoutConstraint!
var defaultHeight: CGFloat!
override func awakeFromNib() {
super.awakeFromNib()
defaultHeight = detailsHeightConstraint.constant
expandButton.button.setTitle("TAP FOR DETAILS", forState: .Normal)
detailsHeightConstraint.constant = 30
}
func expand() {
UIView.animateWithDuration(0.3, delay: 0.0, options: .CurveLinear, animations: {
self.expandButton.arrowImage.transform = CGAffineTransformMakeRotation(CGFloat(M_PI * 0.99))
self.detailsHeightConstraint.constant = self.defaultHeight
self.layoutIfNeeded()
}, completion: { finished in
self.expandButton.button.setTitle("CLOSE", forState: .Normal)
})
}
func collapse() {
UIView.animateWithDuration(0.3, delay: 0.0, options: .CurveLinear, animations: {
self.expandButton.arrowImage.transform = CGAffineTransformMakeRotation(CGFloat(M_PI * 0.0))
self.detailsHeightConstraint.constant = CGFloat(30.0)
self.layoutIfNeeded()
}, completion: { finished in
self.expandButton.button.setTitle("TAP FOR DETAILS", forState: .Normal)
})
}
}
If you want the cell to get physically bigger, then where you have your store IndexPath, in heightForRow: use:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if selectedIndexPath == indexPath {
return 230 + extraHeight
}
return 230.0
}
Then when you want to expand one in the didSelectRow:
selectedIndexPath = indexPath
tableView.beginUpdates
tableView.endUpdates
Edit
This will make the cells animate themselves getting bigger, you dont need the extra animation blocks in the cell.
Edit 2
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if(selectedIndexPath == indexPath) {
selectedIndexPath = nil
if let cell = tableView.cellForRowAtIndexPath(indexPath) as? MyTicketsTableViewCell {
cell.collapse()
}
if let cell = tableView.cellForRowAtIndexPath(NSIndexPath(forRow:indexPath.row+1, section: indexPath.section) as? MyTicketsTableViewCell {
cell.collapse()
}
} else {
selectedIndexPath = indexPath
if let cell = tableView.cellForRowAtIndexPath(indexPath) as? MyTicketsTableViewCell {
cell.expand()
}
if let cell = tableView.cellForRowAtIndexPath(NSIndexPath(forRow:indexPath.row+1, section: indexPath.section) as? MyTicketsTableViewCell {
cell.expand()
}
}
tableView.beginUpdates()
tableView.endUpdates()
}
All you need is implement UITableView Delegate this way:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
By default, estimatedHeight is CGRectZero, when you set some value for it, it enables autoresizing (the same situation with UICollectionView), you can do even also so:
tableView?.estimatedRowHeight = CGSizeMake(50.f, 50.f);
Then you need to setup you constraints inside your cell.
Check this post: https://www.hackingwithswift.com/read/32/2/automatically-resizing-uitableviewcells-with-dynamic-type-and-ns
Hope it helps)
In MyTicketsTableViewController class, inside cellForRowAtIndexPath datasource method add target for the button.
cell.expandButton.addTarget(self, action: "expandorcollapsed:", forControlEvents: UIControlEvents.TouchUpInside)
I tried to implement lots of the given examples on this and other pages with similar questions, but none worked for me since I had to perform some logic in my custom cell (eg. hide unneeded UILables in CustomCell.swift when the cell is collapsed).
Here is the implementation that worked for me:
Create a dictionary:
private var _expandedCells: [IndexPath:Bool] = [:]
Implement the heightForRowAt method:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return _expandedCells[indexPath] == nil ? 70 : _expandedCells[indexPath]! ? 150 : 70
}
Implement the didSelectRowAt method:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
_expandedCells[indexPath] = _expandedCells[indexPath] == nil ? true : !_expandedCells[indexPath]!
tableView.reloadRows(at: [indexPath], with: .fade)
}
Adjust your customCell:
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
guard let cell = cell as? YourCustomTableViewCell, let isExpanded = _expandedCells[indexPath] else { return }
cell.set(expanded: isExpanded)
}
Here's the file I'm using for the table view controller. When I run the project the cell shows the text that's written in "names" but it won't show all of it.
I want it to show the whole text in the same cell. That the cell is sized according to what's written in it.
How do I fix this?
import Foundation
import UIKit
class FTBViewController: UITableViewController {
var names = [String]()
var identities = [String]()
override func viewDidLoad() {
names = ["This is the text the cell is displaying but it won't show it all"]
identities = ["A"]
self.navigationItem.title = "Guía"
self.navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.whiteColor()]
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return names.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("FCell")
cell?.textLabel!.text = names[indexPath.row]
return cell!
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let vcName = identities[indexPath.row]
let viewController = storyboard?.instantiateViewControllerWithIdentifier(vcName)
self.navigationController?.pushViewController(viewController!, animated: true)
}
}
add
cell?.textLabel!.numberOfLines = 0
cell?.textLabel!.lineBreakMode = .ByWordWrapping
cell?.textLabel!.font = UIFont.systemFontOfSize(14.0) // this is optional if you need use this
Full answer
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("FCell")
cell?.textLabel!.numberOfLines = 0
cell?.textLabel!.lineBreakMode = .ByWordWrapping
cell?.textLabel!.font = UIFont.systemFontOfSize(14.0)
cell?.textLabel!.text = names[indexPath.row]
return cell!
}
You could use following code in viewdidLoad :
tableView.estimatedRowHeight = 44.0
tableView.rowHeight = UITableViewAutomaticDimension
Hope so it helps...
My table view can expand and collapse cells when they are pressed, but the content that appears when the cell expands loads before the animation is finished.
What I am left with is this:
What I would like it to look like is this example. This content appears as if it were behind a curtain and the cell expansion animation just reveals it.
Here is the code that controls the table view:
class HistoryViewController: UIViewController, UITableViewDataSource, UITableViewDelegate{
var expandedIndexPath: NSIndexPath? // Index path of the cell that is currently expanded
let collapsedHeight: CGFloat = 44.0 // Constant to set the default collapsed height
var ticketHistoryService = TicketHistoryService() // Service to gather info about Ticket History CoreData
var tickets = [Ticket]()
#IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Remove any appended table view cells
tableView.tableFooterView = UIView()
self.tickets = self.ticketHistoryService.fetchData() // Load inital data
}
// MARK: - Table View Methods
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.tickets.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("cell") as! HistoryTableViewCell
let ticket = self.tickets[indexPath.row]
cell.titleLabel!.text = ticket.ticketNumber
return cell
}
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
self.ticketHistoryService.removeObject(indexPath.row)
self.tickets = self.ticketHistoryService.fetchData()
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
}
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.tableView.beginUpdates()
let cell = self.tableView.cellForRowAtIndexPath(indexPath) as! HistoryTableViewCell
if indexPath.isEqual(self.expandedIndexPath){ // If currently selected cell was just previously selected
self.expandedIndexPath = nil
cell.commentLabel.hidden = true
}
else {
self.expandedIndexPath = indexPath
cell.commentLabel.hidden = false
}
self.tableView.endUpdates()
}
func tableView(tableView: UITableView, willDeselectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath? {
let cell = self.tableView.cellForRowAtIndexPath(indexPath) as! HistoryTableViewCell
cell.commentLabel.hidden = true
return indexPath
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if indexPath.isEqual(self.expandedIndexPath) {
return UITableViewAutomaticDimension
}
return collapsedHeight
}
}
One approach is to have your cell clip subview content that would expand outside of itself:
let cell = self.tableView.dequeueReusableCellWithIdentifier("cell") as! HistoryTableViewCell
cell.clipsToBounds = true
I'm able to expand and collapse cells but i wanna call functions (expand and collapse) inside UITableViewCell to change button title.
import UIKit
class MyTicketsTableViewController: UITableViewController {
var selectedIndexPath: NSIndexPath?
var extraHeight: CGFloat = 100
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! MyTicketsTableViewCell
return cell
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if(selectedIndexPath != nil && indexPath.compare(selectedIndexPath!) == NSComparisonResult.OrderedSame) {
return 230 + extraHeight
}
return 230.0
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if(selectedIndexPath == indexPath) {
selectedIndexPath = nil
} else {
selectedIndexPath = indexPath
}
tableView.beginUpdates()
tableView.endUpdates()
}
}
import UIKit
class MyTicketsTableViewCell: UITableViewCell {
#IBOutlet weak var expandButton: ExpandButton!
#IBOutlet weak var detailsHeightConstraint: NSLayoutConstraint!
var defaultHeight: CGFloat!
override func awakeFromNib() {
super.awakeFromNib()
defaultHeight = detailsHeightConstraint.constant
expandButton.button.setTitle("TAP FOR DETAILS", forState: .Normal)
detailsHeightConstraint.constant = 30
}
func expand() {
UIView.animateWithDuration(0.3, delay: 0.0, options: .CurveLinear, animations: {
self.expandButton.arrowImage.transform = CGAffineTransformMakeRotation(CGFloat(M_PI * 0.99))
self.detailsHeightConstraint.constant = self.defaultHeight
self.layoutIfNeeded()
}, completion: { finished in
self.expandButton.button.setTitle("CLOSE", forState: .Normal)
})
}
func collapse() {
UIView.animateWithDuration(0.3, delay: 0.0, options: .CurveLinear, animations: {
self.expandButton.arrowImage.transform = CGAffineTransformMakeRotation(CGFloat(M_PI * 0.0))
self.detailsHeightConstraint.constant = CGFloat(30.0)
self.layoutIfNeeded()
}, completion: { finished in
self.expandButton.button.setTitle("TAP FOR DETAILS", forState: .Normal)
})
}
}
If you want the cell to get physically bigger, then where you have your store IndexPath, in heightForRow: use:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if selectedIndexPath == indexPath {
return 230 + extraHeight
}
return 230.0
}
Then when you want to expand one in the didSelectRow:
selectedIndexPath = indexPath
tableView.beginUpdates
tableView.endUpdates
Edit
This will make the cells animate themselves getting bigger, you dont need the extra animation blocks in the cell.
Edit 2
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if(selectedIndexPath == indexPath) {
selectedIndexPath = nil
if let cell = tableView.cellForRowAtIndexPath(indexPath) as? MyTicketsTableViewCell {
cell.collapse()
}
if let cell = tableView.cellForRowAtIndexPath(NSIndexPath(forRow:indexPath.row+1, section: indexPath.section) as? MyTicketsTableViewCell {
cell.collapse()
}
} else {
selectedIndexPath = indexPath
if let cell = tableView.cellForRowAtIndexPath(indexPath) as? MyTicketsTableViewCell {
cell.expand()
}
if let cell = tableView.cellForRowAtIndexPath(NSIndexPath(forRow:indexPath.row+1, section: indexPath.section) as? MyTicketsTableViewCell {
cell.expand()
}
}
tableView.beginUpdates()
tableView.endUpdates()
}
All you need is implement UITableView Delegate this way:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
By default, estimatedHeight is CGRectZero, when you set some value for it, it enables autoresizing (the same situation with UICollectionView), you can do even also so:
tableView?.estimatedRowHeight = CGSizeMake(50.f, 50.f);
Then you need to setup you constraints inside your cell.
Check this post: https://www.hackingwithswift.com/read/32/2/automatically-resizing-uitableviewcells-with-dynamic-type-and-ns
Hope it helps)
In MyTicketsTableViewController class, inside cellForRowAtIndexPath datasource method add target for the button.
cell.expandButton.addTarget(self, action: "expandorcollapsed:", forControlEvents: UIControlEvents.TouchUpInside)
I tried to implement lots of the given examples on this and other pages with similar questions, but none worked for me since I had to perform some logic in my custom cell (eg. hide unneeded UILables in CustomCell.swift when the cell is collapsed).
Here is the implementation that worked for me:
Create a dictionary:
private var _expandedCells: [IndexPath:Bool] = [:]
Implement the heightForRowAt method:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return _expandedCells[indexPath] == nil ? 70 : _expandedCells[indexPath]! ? 150 : 70
}
Implement the didSelectRowAt method:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
_expandedCells[indexPath] = _expandedCells[indexPath] == nil ? true : !_expandedCells[indexPath]!
tableView.reloadRows(at: [indexPath], with: .fade)
}
Adjust your customCell:
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
guard let cell = cell as? YourCustomTableViewCell, let isExpanded = _expandedCells[indexPath] else { return }
cell.set(expanded: isExpanded)
}
I have a UITableView, and added it as a subview of a UIView.
Whenever I select a cell that had everything disappears in UITableView.
Already had this problem at other times, however it stopped happening without changes on code.
Currently I use Swift, however already happened in Objective-C.
Code:
TableView delegates:
numberOfSectionsInTableView
numberOfRowsInSection
cellForRowAtIndexPath
heightForRowAtIndexPath
didSelectRowAtIndexPath
Also registered the identifier of the cell
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "Cell")
listObjectsToList = ["String 1","String 2","String 3"]
self.view.frame.size = CGSizeMake(300, 110)
self.view.layer.cornerRadius = 5
self.view.layer.masksToBounds = true
self.tableView.scrollEnabled = false
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return listObjectsToList.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell: UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("Cell") as UITableViewCell
cell.textLabel.text = listObjectsToList.objectAtIndex(indexPath.row) as? String
return cell
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 40
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.tableView.deselectRowAtIndexPath(indexPath, animated: true)
let objectSelected: AnyObject = listObjectsToList.objectAtIndex(indexPath.row)
object.type = objectSelected as String
self.view.removeFromSuperview()
}
However the method didSelectRowAtIndexPath is not called...
Code adding tableview:
var listTypeTableViewController = ListTypeTableViewController()
listTypeTableViewController.view.frame = CGRectMake(10, 80, 300, 130)
self.view.addSubview(listTypeTableViewController.view)
I have tried:
var listTypeTableViewController = ListTypeTableViewController()
listTypeTableViewController.view.frame = CGRectMake(10, 80, 300, 130)
self.view.addSubview(listTypeTableViewController.tableView)
But without success
The problem was and I was just trying to extract the UITableView to show it. When I need to add a UITableViewController as a child of my UIViewController:
var listTypeTableViewController = ListTypeTableViewController(nibName: "TableViewTypeScheduling", bundle: nil)
listTypeTableViewController.view.frame = CGRectMake(10, 80, 300, 130)
addChildViewController(listTypeTableViewController)
view.addSubview(listTypeTableViewController.view)
The reason is this line in tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) method:
self.view.removeFromSuperview()
You remove a view and all of its superviews, including the table view.