UITableView delegate and datasource in external class does not work - ios

I have a simple project, with UITableView added as subview of the current view, and external tableviewcontroller class that make a delegate and datasource.
The problem is that all work correctly excepted delegate didSelectedRowAtIndexPath, when I click in a single row, all tableview become white, here is the code:
MAIN CLASS:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let cont:Tbcontroller = Tbcontroller()
let tableViewInner = UITableView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width-(self.view.frame.width/6), height: 180))
tableViewInner.scrollEnabled = false
tableViewInner.separatorStyle = .None
tableViewInner.allowsSelection = true
tableViewInner.userInteractionEnabled = true
cont.type = 1
cont.setCurrentTableView(tableViewInner)
self.view.insertSubview(tableViewInner, atIndex: self.view.subviews.count+1)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
EXTERNAL CLASS DELEGATE DATASOURCE:
import UIKit
class Tbcontroller: UITableViewController {
var type:Int = 1
override func viewDidLoad() {
super.viewDidLoad()
}
func getCell() -> UITableViewCell{
let presentCell: UITableViewCell = UITableViewCell()
return presentCell
}
func setCurrentTableView(table:UITableView){
self.tableView = table
self.tableView.delegate = self
self.tableView.dataSource = self
self.tableView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 4
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = getCell()
cell.textLabel?.text = "ciao"
cell.textLabel?.font = UIFont.systemFontOfSize(13)
return cell
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 100
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("clicked")
}
}
When I click, I do not see the output "clicked"

Your main problem is that TbController() get deallocated. dataSource and delegate properties on UITableView are weak. Therefor, because you only assign TbController to a local variable and to the weak properties, it will get deallocated.
Also, the UITableViewController already creates a TableView for you. It is not good practice to "recreate" it. I would rather make use of the TableView in the UITableViewController and add the UITableViewController's view as a subview to your UIViewController's view.
To fix, you need an instance variable for TbController.
Sample code with ivar for TbController and making use of Tbcontroller's UITableView.
import UIKit
class ViewController: UIViewController {
var cont: Tbcontroller = Tbcontroller()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
cont.type = 1
self.view.addSubview(cont.view)
}
}
import UIKit
class Tbcontroller: UITableViewController {
var type:Int = 1
override func viewDidLoad() {
super.viewDidLoad()
tableView.scrollEnabled = false
tableView.separatorStyle = .None
tableView.allowsSelection = true
tableView.userInteractionEnabled = true
self.tableView.delegate = self
self.tableView.dataSource = self
}
func getCell() -> UITableViewCell{
let presentCell: UITableViewCell = UITableViewCell()
return presentCell
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 4
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = getCell()
cell.textLabel?.text = "ciao"
cell.textLabel?.font = UIFont.systemFontOfSize(13)
return cell
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 100
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("clicked")
}
}

thanks to Carien, it works fine, i changed uitableviewcontroller with:
: NSObject, UITableViewDataSource, UITableViewDelegate

Related

UITableView - Not showing

I have set up tableview many times but don't why is not it showing anything. I have added a tableview on my storyboard file, added reference on ViewController file and set datasource and delegate on storyboard. on viewDidLoad registered the cell and finally added reusableIdentifier on TableViewCell. Here is my code with details configuration :
import UIKit
struct ViewControllerConstants {
static let kCellIdentifier = "TableViewCell"
static let kNibName = "TableViewCell"
}
class ViewController: UIViewController {
var cellImageNames : [String] = ["image1","image2","image3","image4","image5","image6"]
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.tableView.register(UINib.init(nibName: ViewControllerConstants.kNibName, bundle: nil), forCellReuseIdentifier: ViewControllerConstants.kCellIdentifier)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewWillAppear(_ animated: Bool) {
self.tableView.reloadData()
}
}
extension ViewController : UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cellImageNames.count
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: ViewControllerConstants.kCellIdentifier, for: indexPath) as? TableViewCell {
cell.contentImageView.image = UIImage.init(named: cellImageNames[indexPath.row])
return cell
}
return UITableViewCell.init()
}
}
extension ViewController : UITableViewDelegate {
}
Try to remove identifiers for cells in storyboard.
Problem: Cell height was not defined on code. So it was creating cell with 0 height value .
Solution: Need to specify height of each row as below code:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}

Update a table in the detailview of a uisplitviewcontroller

So I have a UISplitViewController and in the DetailView I have a UITableView.
What I want to do is take the selected cell from the root view controller and append it to the string which is populating my tableview in the detail view controller. I can append with selection very easily but I need help with is the updating part.
What's supposed to happen is when you click the cell, it appends the value in the cell to the global variable main.BoatManifest, and then update the table. I just don't know how to do that.
Here's some code:
import UIKit
class DetailViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, FullListCellDelegate {
#IBOutlet weak var tableView: UITableView!
func updateName(sender: FullListCell, detVC: DetailViewController) {
tableView.reloadData()
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return main.BoatManifest.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
// Configure the cell...
cell.textLabel?.text = main.BoatManifest[indexPath.row]
return cell
}
}
struct Main {
var BoatManifest: [String] = []
}
var main = Main(BoatManifest: [" "])
This is the code for my detail view and the struct Main on the bottom is just a global variable. My MainView code is this:
import UIKit
protocol NameSelectionDelegate: class {
func nameSelected()
}
class MasterViewController: UITableViewController {
var Names: [String] = ["John", "Mark", "Paul", "Jeremy"]
override func viewDidLoad() {
super.viewDidLoad()
if let split = self.splitViewController {
let controllers = split.viewControllers
self.detailViewController = (controllers[controllers.count-1] as! UINavigationController).topViewController as? DetailViewController
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return Names.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = Names[indexPath.row]
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
main.BoatManifest.append(Names[indexPath.row])
NotificationCenter.default.addObserver(self, selector: #selector(loadList), name: NSNotification.Name(rawValue: "load"), object: nil)
}
func loadList(){
//load data here
self.tableView.reloadData()
}
}
I attempted to use a UISplitViewController tutorial to figure it out but it didn't have the tableview in the detail view controller. I need to send a message when I select the cell to the detail tableview and have it update with the appended text.
Thanks for your help.

Swift using view from other controller as the background of a uitableview

I am new to swift and am trying to create an app with a table view which can use the view from another UIView controller.
Is it doable?
If so please help me with it, I have attached my code for the main controller below. Please let me know if anything is wrong?
Thank you so much.
import UIKit
class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
var numbers:[String] = []
let vc = bgViewController()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
tableView.backgroundView = vc.view
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if(numbers.count == 0){
tableView.backgroundView?.hidden = false
println("1")
}
else{
tableView.backgroundView?.hidden = true
}
return numbers.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! UITableViewCell
return cell
}
}
import UIKit
class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
var numbers:[String] = []
var vc: bgViewController!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
vc = self.storyboard.instantiateViewControllerWithIdentifier("bgViewController") as! bgViewController
tableView.backgroundView = vc.view
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if(numbers.count == 0){
tableView.backgroundView?.hidden = false
println("1")
}
else{
tableView.backgroundView?.hidden = true
}
return numbers.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! UITableViewCell
return cell
}
}
Provide storyboard identifier as bgViewController in attribure inspector.

Setting up a Table View Controller in Swift?

I'm trying to create a table as the main screen of my app and I'm having some issues. I set up the main.storyboard correctly, but there's an override func I have that "doesn't override a superclass". The error is on the nuberOfRowsInSection override func line. Here's my code:
import UIKit
class ViewController: UITableViewController {
var candies = [Candy]()
#IBOutlet weak var editButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup
// after loading the view.
self.candies = [Candy(name: "Jolly Rancher"),Candy(name: "Snickers"),Candy(name: "Twix"),Candy(name: "Butterfinger"),Candy(name: "Milky Way")]
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func tableView(tableView: UITableView, nuberOfRowsInSection section: Int) -> Int {
return self.candies.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
var candy : Candy
candy = candies [indexPath.row]
cell.textLabel?.text = candy.name
}
#IBAction func editButtonPressed(sender: UIButton) {
editButton.setTitle("Save", forState: UIControlState.Normal)
}
}
Just a guess:
// this should read "numberOfRowsInSection": ~~v
override func tableView(tableView: UITableView, nuberOfRowsInSection section: Int) -> Int {
return self.candies.count
}
As far as I know, UITableViewController does not have a method with a parameter nuberOfRowsInSection, but it does have one with a parameter numberOfRowsInSection.
When dealing with something that isn't working, please start by checking your code for spelling mistakes.
You have a typing mistake. You call the method nuberOfRowsInSection. There is a 'n' missing. The method should be called numberOfRowsInSection.
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.candies.count
}
Also you have en error in your cellForRowAtIndexPath method. You have to return the cell:
return cell

creating table view using swift

I have been trying to create a table view using swift using xcode 6 and ios8 but I am not getting anything on my simulator,simply it showing empty(white).
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var myArr = ["one","two","three","four","five"]
#IBOutlet weak var table: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return myArr.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "cell")
cell.textLabel?.text = self.myArr[indexPath.row]
return cell;
}
}
I have even tried by dragging some elements like button, switch, etc, and I am not getting anything on simulator. If I download and run any code its working.
Here my worked code, i dont understand what was wrong in previous one,but i have created a new project then it worked.
i just dragged a table view to viewcontroller and assigned delegate and datasource
then came to viewcontroller.swift and tried
import UIKit
class ViewController: UIViewController {
var items = ["a","b","c"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return self.items.count
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 2
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
var cell:UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "myCell") as UITableViewCell
cell.textLabel?.text = self.items[indexPath.row]
return cell
}
}
Is dataSource of table set in Interface builder? You can do it in code as well:
override func viewDidLoad() {
super.viewDidLoad()
table.dataSource = self
}
You are missing numberOfSectionsInTableView from the UITableViewDataSource protocol:
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
Your 'table' delegate is not set. Add:
table.delegate = self
to your viewDidLoad above
table.dataSource = self
you missed delegate and dataSource please add following lines in viewDidLoad
table.delegate = self
and
table.dataSource = self

Resources