UITableView Swift not scrolling. Guys I have this table view with three different cells and the table view renders on the simulator just fine but when i scroll it immediately jumps back to the top.
import UIKit
class WalkthroughScreen2ViewController: UIViewController , UITableViewDataSource,UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.estimatedRowHeight = 300
tableView.rowHeight = UITableViewAutomaticDimension
tableView.scrollEnabled = true
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Return the number of rows in the section.
return 4
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) ->
UITableViewCell {
println(indexPath.row)
if(indexPath.row == 0){
var cell: wkscreen2Cell1TableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell1") as wkscreen2Cell1TableViewCell
return cell
}
if(indexPath.row == 1){
var cell: wkscreen2Cell2TableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell2") as wkscreen2Cell2TableViewCell
return cell
}
if(indexPath.row == 2){
println("cell3")
var cell: wkscreen2Cell3TableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell3") as wkscreen2Cell3TableViewCell
return cell
}
return UITableViewCell()
}
}
I landed on your question, because I had the same one.
To scroll in a simulator, you press and move your cursor up and down. If you are still not able to scroll, it must be a bug.
Your TableView must be scroll, when count of your cells > 10, for example(4-inch screen). Test to do: Add ten cells for TableView. And it must be worked.
Why do you return 4 in numberOfRowsInSection when you are obviously only showing 3 cells ? Have you tried setting that to 3 ?
I had the same problem. After putting "tableView.dataSource = self" and "tableView.delegate = self" on "viewDidLoad()", the problem was solved.
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
}
quit the stimulator, clean shift+command+k then run the (command+R) should work.
Related
I have a normal view controller with a table view inside, so the class is just a normal UIViewController, therefor I am unable to call self.tableView with this.
I have an asynchronous call to create an array of Aircraft objects that is taken from an online database, but that is only completed after the table cells are initially loaded. I am trying to update the table cells after this asynchronous call is completed, but am unsure how to do so.
I do the async call in viewDidLaod(). Here is my current code that only displays the loading tags since the update has not taken place for the aircraft array.
class AircraftViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
let log = Logger( id: String(AircraftViewController.self) )
let dvc = DownloadViewController()
var aircraftArr = [Aircraft]()
override func viewDidLoad() {
super.viewDidLoad()
dvc.getMobileSystemOverviewHTML {
dispatch_async(dispatch_get_main_queue()){
self.aircraftArr = self.dvc.aircraft
self.log.debug("\n\n\n\n\n \(self.aircraftArr) \n\n\n\n\n")
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table View Delegate Methods
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("AircraftCell", forIndexPath: indexPath) as! AircraftCell
if indexPath.row < aircraftArr.count{
let singleAircraft = aircraftArr[indexPath.row] as Aircraft
cell.aircraft = singleAircraft
} else {
cell.aircraft = Aircraft(tailID: "Loading", aircraftSN: "Loading", Box_SN: "Loading")
}
return cell
}
You need to create the outlet of tableview like this
#IBOutlet var tableView: UITableView!
After that reload this tableview in your dispatch_async
dvc.getMobileSystemOverviewHTML {
dispatch_async(dispatch_get_main_queue()){
self.aircraftArr = self.dvc.aircraft
self.tableView.reloadData()
self.log.debug("\n\n\n\n\n \(self.aircraftArr) \n\n\n\n\n")
}
}
Hope this will help.
My goal is to make a grouped tableView, but for somehow the data is not added to the table View
Here's the story board picture
I added a table View on top of view controller which is
and the code that I wrote seems like it don't work
import UIKit
import Alamofire
import SwiftyJSON
import KeychainAccess
class SettingsViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
let keychain = Keychain(server: "https://genietesting.herokuapp.com", protocolType: .HTTPS)
var profile: [String]?
let aboutGenie = [
"How it works",
"About",
"Contact"
]
override func viewDidLoad() {
super.viewDidLoad()
let firstName = keychain[string: "first_name"]
profile = [
firstName!
]
tableView.dataSource = self
tableView.delegate = self
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 2
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return profile!.count
} else {
return aboutGenie.count
}
}
func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if section == 0 {
return "Profile"
} else {
return "About Genie"
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let tableCell = tableView.dequeueReusableCellWithIdentifier("myCell")
return tableCell!
}
}
and of course, I want to make it clickable so that it would go to its own viewController
After some suggestion, I changed most of my codes above and the result is still the same but this time it shows the header
The result is
airsoftFreak,
There are multiple mistakes I can figure out
There is no IBOutlet for your tableView which is added on top of your ViewController.
So you must be having something like
#IBOutlet var tableView: UITableView!
Your SettingsViewController only confirms to UITableViewDataSource and not to UITableViewDelegate. If you wamt to get didSelectRowAtIndexPath to be triggerred you have to confirm to UITableViewDelegate
class SettingsViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
As many have noticed and mentioned in their answer you will have to set your viewController as delegate for both UITableViewDelegate,UITableViewDataSource so
self.tableView.dataSource = self
self.tableView.delegate = self
The way you are instantiating cell is wrong as well :) Yopu should not create tableViewCell everytime for each cell :) Go to your TableView in storyBoard add a prototype cell, decorate it the way you want and the set the reusableIndentifier for it. Lets say reusableIndentifier you set is 'myCell'
your cellForRowAtIndexPath will change to
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//assuming you have different cells for each section
switch indexPath.section {
case 0: let tableCell = tableView.dequeueReusableCellWithIdentifier("myCell")
tableCell.textLabel.text = profile[indexPath.row]
return tableCell
//in swift switch has to be exhaustive so default
default: let secondSectionCell = tableView.dequeueReusableCellWithIdentifier("second_section_cell_identifier")
secondSectionCell.textLabel.text =aboutGenie[indexPath.row]
return secondSectionCell
}
}
Try to drag (ctrl+drag) the tableview to the yellow button at the top of the viewcontroller. You will now see to options: datasource and delegate. Choose one of these to and perform the action again for the other. Now the tableview should be linked to your code.
If the option to make it clickable was a question as well:
With the function didSelectRowAtIndexpath, you can achieve this. There should be a lot of stacks about this issue available.
You probably have not wired the UITableView delegate and dataSource methods to the viewController. You can do this in two ways.
1. programatically
create a tableViewOutlet
override fun viewDidLoad() {
super.viewDidLoad()
yourTableViewOutlet.delegate = self
yourTableViewOutlet.dataSource = self
}
in interfaceBuilder
a) open the document outline in the storyboard.
b) control drag from your tableView to your ViewController.
c) connect delegate and dataSource one by one.
click on the cell will fire the delegate method didSelectRowAtIndexPath
self.tableView.delegate and self.tableView.datasource
override func viewDidLoad() {
super.viewDidLoad()
let firstName = keychain[string: "first_name"]
profile = [
firstName!
]
self.tableView.delegate = self
self.tableView.datasource = self
}
I have 2 sections, First have 1 row and Second have 4 rows. I can see the switch, labels and text fields in the storyboard. It is loading blank in the Simulator. I have checked all the IBOutlets are connected.
Following is my code from Table View Controller
import UIKit
class InfoTableViewController: UITableViewController {
var sectionArray: NSMutableArray = ["Social Security Benefits", "Demographics"]
var socialArray: NSMutableArray = ["Estimate Social Security Benefits"]
var demoArray: NSMutableArray = ["Name:", "DOB:", "Age of Retirement:", "Years of Retirement"]
override func viewDidLoad() {
super.viewDidLoad()
}
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 Potentially incomplete method implementation.
// Return the number of sections.
return self.sectionArray.count
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0{
return socialArray.count
} else {
return demoArray.count
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if indexPath.section == 0 {
if indexPath.row == 0 {
println(indexPath.section)
println(indexPath.row)
let cell: SocialTableCell = SocialTableCell(style: UITableViewCellStyle.Default, reuseIdentifier: "social")
cell.social?.text = "Estimate"
cell.toggle?.setOn(false, animated: true)
return cell
}
} else if indexPath.section == 1 {
if indexPath.row == 0 {
println(indexPath.section)
println(indexPath.row)
let cell: NameTableCell = NameTableCell(style: UITableViewCellStyle.Default, reuseIdentifier: "name")
return cell
}else if indexPath.row == 1{
println(indexPath.section)
println(indexPath.row)
let cell: DOBTableCell = DOBTableCell(style: UITableViewCellStyle.Default, reuseIdentifier: "DOB")
}else if indexPath.row == 2{
println(indexPath.section)
println(indexPath.row)
let cell: RetirementTableCell = RetirementTableCell(style: UITableViewCellStyle.Default, reuseIdentifier: "AgeOfRetirement")
}else if indexPath.row == 3{
println(indexPath.section)
println(indexPath.row)
let cell: YearsRetirementTableCell = YearsRetirementTableCell(style: UITableViewCellStyle.Default, reuseIdentifier: "YearsOfRetirement")
}
}
return UITableViewCell()
//cell.configureFlatCellWithColor(UIColor.greenSeaColor(), selectedColor: UIColor.cloudsColor(), roundingCorners: UIRectCorner())
}
}
I also have created 5 Table View Cells Classes for each cell. I also have checked for all the identifiers and they are correct.
Following is the image of my storyboard
But when i run it, the simulator only shows sections and the cells are empty.
Any Help will be highly appreciated.
Thanks
You can do this with using Static cells.
Go to your Table view => Attribute Inspector => in content select static cells, then in section , put 2 ( because you have 2 sections )
Then Click a one section in Storyboad Hierarchy => Attribute Inspector => put number of rows ( put 1 because you have one row in 1st section ) you want in each section.Again select the other section and put number of rows you want( put 4 becuase you have 4 rows in 2nd section)
Then Click the each row cell and add Label and put your label name. and you can put toggle button too for tour first section.
Create a new cocoa touch class :- The class look like this ( You Should comment or deleter these functions ,
// MARK: - Table view data source
/*
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete method implementation.
// Return the number of rows in the section.
return 2
}
*/
/*
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath) as! UITableViewCell
// Configure the cell...
return cell
}
*/
And Finally Table class looks like this ,
import UIKit
class TableViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
}
}
This is how your cellForRowAtIndexPath: should look like. Below is an example from your first section first row, you can align all others accordingly.
As a side note, noticed that except for your first section first row, for all other table rows you are not setting any labels etc. and that control end up coming to statement return UITableViewCell() leading to empty cells. Please double check that too.
if indexPath.row == 0 {
println(indexPath.section)
println(indexPath.row)
let socialCellId: NSString = "social"
var cell: SocialTableCell = tableView.dequeueReusableCellWithIdentifier(socialCellId) as SocialTableCell
if cell == nil
{
cell = SocialTableCell(style: UITableViewCellStyle.Default, reuseIdentifier:socialCellId)
}
cell.social?.text = "Estimate"
cell.toggle?.setOn(false, animated: true)
return cell
}
I had the exact same issue, and none of the comments above helped me. I finally figured it out, perhaps you were having the same issue.
For me, I had accidentally copied and pasted a second tableview in the designer. The second tableView was on top of the first but only the first table view was connected to my TableViewController, and so the cells for the visible one at runtime were never created, hence blank.
Check that, hopefully that helps.
Double TableView
I'm using Xcode 7.0, Swift 2
I'm basically trying to create a custom class that will build a UITable, then in the ViewController I make a new object of the table and load it into self.view;
The problem I'm having is that the function func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell isn't being called at all from within the custom class. I've been looking for a solution for 3 days now and I've tried rebuilding the App and code several times with no luck.
Please note, if I use the same code (that is everything required to build the table; excluding init functions, etc) in the ViewController.swift file, it works fine.
I know the problem is with the cellForRowAtIndexPath function because it will not print out the statement I set in that block of code when it runs. All other functions are called, but for some reason this isn't being called. Not sure if I overlooked something here. Any help would be appreciated. Thanks in advance.
class sideTest: NSObject, UITableViewDelegate, UITableViewDataSource {
let tesTable: UITableView = UITableView()
var items: [String]?
var mView: UIView = UIView()
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print("The number of rows is: \(self.items!.count)")
return self.items!.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
print("\nLets create some cells.")
let sCell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier("cell") as UITableViewCell!
sCell.textLabel?.text = self.items![indexPath.row]
sCell.textLabel?.textColor = UIColor.darkTextColor()
return sCell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("You selected cell #\(indexPath.row)!")
}
func tblSetup() {
self.tesTable.frame = CGRectMake(0, 0, 320, mView.bounds.height)
self.tesTable.delegate = self
self.tesTable.dataSource = self
self.tesTable.backgroundColor = UIColor.cyanColor()
// load cells
self.tesTable.registerClass(UITableViewCell.self, forCellReuseIdentifier: "Cell")
self.tesTable.reloadData()
print("Currenlty in tblSetup.\nCurrent rows is: \(self.items!.count)")
}
//Init
override init() {
super.init()
self.items = nil
self.tblSetup()
}
init(sourceView: UIView , itemListAsArrayString: [String]) {
super.init()
self.items = itemListAsArrayString
self.mView = sourceView
self.tblSetup()
}
}
Here is the code from ViewController.swift; Please do note that the table gets built, but the cells do not populate, even if I manually enter cell info by doing: sCell.textLabel?.text = "test cell"
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let myTable: sideTest = sideTest(sourceView: self.view, itemListAsArrayString: ["Cell 1", "Cell 2", "Cell 3"])
self.view.addSubview(myTable.tesTable)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Again, any help is greatly appreciated. Thanks.
Your view controller don't have a strong reference to your sideTest var.
Once your view did load finished,your sideTest is nil.Although you have a tableview(by add subview), but you no longer have a data source.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {}
is called after view did load. That cause the problem.
change your view controller to:
var tb :sideTest?
override func viewDidLoad() {
super.viewDidLoad()
let myTable: sideTest = sideTest(sourceView: self.view, itemListAsArrayString: ["Cell 1", "Cell 2", "Cell 3"])
print(myTable.tesTable.frame)
tb=myTable
self.view.addSubview(myTable.tesTable)
}
change your cellforrowatindexpath to:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
print("create cells")
var cell :UITableViewCell?
if let sCell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier("cell"){
cell=sCell
}else{
cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "cell")
}
cell!.textLabel?.text = self.items![indexPath.row]
cell!.textLabel?.textColor = UIColor.darkTextColor()
return cell!
}
this will fix most of the problems.
Your code:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let myTable: sideTest = sideTest(sourceView: self.view, itemListAsArrayString: ["Cell 1", "Cell 2", "Cell 3"])
self.view.addSubview(myTable.tesTable)
}
I would think that the myTable variable goes out of scope and is released when viewDidLoad finishes, so there is no data source or delegate after that. Did you verify that the self.view.addSubview(myTable.tesTable) retains it? Try moving declaration of myTable outside of the function level (to property level) or add a diagnostic print to deinit..
EDIT Answer below in this post
I'm trying to set up a UITableView controller in storyboard, with a separate datasource, and I've hit a wall. The data source doesn't seem to respond to changes or push it's 'updates' to the table view. I've tried implementing the data source in the MainMenuTableViewController which worked fine.
This is my MainMenuTableViewController
override func viewDidLoad() {
super.viewDidLoad()
sharedLightsManager.delegate = self
sharedLightsManager.loadNetworkContext()
dataSource = MainMenuTableViewDataSource(sharedLightsManager: sharedLightsManager)
tableView.dataSource = dataSource
tableView.delegate = dataSource
title = "test"
}
//This method fires each time a change happens
func updateLights(){
lights = sharedLightsManager.localNetworkContext.allLightsCollection.lights
tableView.reloadData()
}
MainMenuDataSource:
class MainMenuTableViewDataSource: NSObject, UITableViewDataSource, UITableViewDelegate
{
let reuseIdentifier = "tableViewCell"
var sharedLightsManager: SharedLightsManager?
var lights = []
init(sharedLightsManager: SharedLightsManager)
{
self.sharedLightsManager = sharedLightsManager
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return lights.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier("tableViewCell", forIndexPath: indexPath) as UITableViewCell
var lights = sharedLightsManager!.localNetworkContext.allLightsCollection.lights
var light = LFXLight()
if lights.count == 0 {
println("Lights array still loading...")
} else {
light = lights[indexPath.row] as LFXLight
}
return cell
}
}
and here is my outlets:
I've just figured it out. A bit embarrassing. It was due to the lights array not having any objects in it, so obv. lights.count would return 0, therefore no rows...
The data source will not push updates unless the UITableView is told to reloadData. If you change the numberOfRows value, it will not update unless the tableView is notified through methods like insertRowAtIndexPath, reloadData, deleteRowAtIndexPath etc.