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
Related
This question already has an answer here:
deleteRowsATIndexPaths crashing [duplicate]
(1 answer)
Closed 7 years ago.
hi this is my code i keep getting the error when I delete a row.
I know that my array is not being updated as i delete a row and hence the error. Orerlist.list is an array getting my data
How many i resolve this issue?
Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (1) must be equal to the number of rows contained in that section before the update (1), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'
class RootTableViewController: UITableViewController,MenuItemSelectionDelegate {
var orderList = OrderList()
var delegate:MenuItemSelectionDelegate! = nil
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.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// Return the number of sections.
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Return the number of rows in the section.
return orderList.list.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
cell.textLabel?.text = orderList.list[indexPath.row].menuItem
return cell
}
// Override to support conditional editing of the table view.
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
// Override to support editing the table view.
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
// Delete the row from the data source
self.tableView.beginUpdates()
self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
self.tableView.endUpdates()
} else if editingStyle == .Insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "reserve"{
let vc = segue.destinationViewController as! BeautyViewController
vc.delegate = self
}
}
func didSelectMenuItem(controller: UITableViewController, order: OrderModel) {
orderList.addList(order)
controller.navigationController?.popViewControllerAnimated(true)
tableView.reloadData()
}
}
You have to delete the corresponding element from the orderList.list as well.
Otherwise you tell the tableview you delete some data, it then re-queries the data and finds out that the data stayed the same - a contradiction to what you have just told it.
Something like
orderList.list.removeAtIndex(indexPath.row)
I am working on an app that needs to display five different images inside of five different tableview cells. This is the storyboard that I have for the cell.
This is the code I have inside of the tableviewcontroller.
class MasterViewController: UITableViewController, UITableViewDelegate, UITableViewDataSource {
var returnTable = 1
var icons: [String] = ["settings", "calendar", "classes", "envelope", "grades"]
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.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
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 0
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete method implementation.
// Return the number of rows in the section.
return icons.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! HomeScreenCells
var image : UIImage = UIImage(named: icons[indexPath.row])!
cell.icon.image = image
return cell
}
I also have a custom class for the tableviewcells. Also, I have the correct reuse identifier for the cell. Still, the image does not appear. Not only does the image not appear, nothing appears. When I change the background, the background does not change in the simulator. This is all I get in the simulator.
I have the classes linked up correctly for the split view controller. I have no idea why nothing is appearing in the table. Any help would be appreciated.
I think your problem may be that you have the number of sections set to 0. Either set it to 1, or leave out the block of code completely.
As stated above, return 1 in number of sections (or the number of cells you need). And if your custom cell class has a .xib, you also need to register it, sometimes after you init the tableview
tableView.registerNib( UINib(nibName: "HomeScreenCells", bundle: nil), forCellReuseIdentifier: "Cell")
I am using parse.com framework with Swift and in PFQueryTableViewController when I set the pagination it won't work. If the DB has less rows than the number set in objectPerPage it works fine, but if there are more rows and when I run the app it keeps showing the loading screen and nothing is downloaded, when I do "swipe as refresh" it crash as
Error
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 5 beyond bounds [0 .. 4]
ImagesTableViewController.swift
import UIKit
import Parse
import ParseUI
import Bolts
class ImagesTableViewController: PFQueryTableViewController {
#IBAction func unwindToSegue (segue : UIStoryboardSegue) {}
// Initialise the PFQueryTable tableview
override init(style: UITableViewStyle, className: String!) {
super.init(style: style, className: className)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
// Configure the PFQueryTableView
self.parseClassName = "Image"
self.pullToRefreshEnabled = true
self.paginationEnabled = true
self.objectsPerPage = 5
}
// Define the query that will provide the data for the table view
override func queryForTable() -> PFQuery {
var query = PFQuery(className: "Image")
query.whereKey("deleted", notEqualTo: 1)
query.orderByDescending("createdAt")
return query
}
//override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFTableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("ImageCell") as! ImageTVCell!
if cell == nil {
cell = ImageTVCell(style: UITableViewCellStyle.Default, reuseIdentifier: "ImageCell")
}
// Extract values from the PFObject to display in the table cell HEADLINE
if let caption = object?["caption"] as? String {
cell?.headlineLabel?.text = caption
}
// Display image
var initialThumbnail = UIImage(named: "question")
cell.postImageView.image = initialThumbnail
if let thumbnail = object?["image"] as? PFFile {
cell.postImageView.file = thumbnail
cell.postImageView.loadInBackground()
}
return cell
}
// if I remove this code pagination work but the cell height is wrong
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return calculateHeightForRowAtIndexPath(indexPath)
}
func calculateHeightForRowAtIndexPath(indexPath: NSIndexPath) -> CGFloat {
if let ratio = objectAtIndexPath(indexPath)?["aspect"] as? Float {
println("Ratio: \(ratio)")
return tableView.bounds.size.width / CGFloat(ratio)
} else {
return 50.0
}
}
#IBAction func addNewPhotoButton(sender: UIBarButtonItem) {
self.tabBarController?.tabBar.hidden = true
self.performSegueWithIdentifier("showUploadNewImage", sender: self)
}
}
This problem occurs because of PFQueryTableViewController's implementation of the method tableView:numberOfRowsInSection from the UITableViewDataSource. I've copy/pasted it from the GitHub repo containing PFQueryTableViewController.m
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSInteger count = [self.objects count];
if ([self _shouldShowPaginationCell]) {
count += 1;
}
return count;
}
It simply returns the count of objects to display (which makes sense), but if pagination is enabled, then it requires for an extra cell to be shown. This means you have to manually created another cell with the text "Load more data" or something like that, which would trigger a refresh.
A way to overcome this is simply by overriding tableView:numberOfRowsInSection yourself with the following:
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.objects!.count
}
UPDATE 1
The prebuilt Parse pagination button was gone in previous answer
Use the following code snippet for calculating the height of the cells to display the prebuilt Parse pagination button
func calculateHeightForRowAtIndexPath(indexPath: NSIndexPath) -> CGFloat {
// Special case for pagination, using the pre-built one by Parse
if (indexPath.row >= objects!.count) { return 50.0 }
// Determines the height if an image ratio is present
if let ratio = objectAtIndexPath(indexPath)?["aspect"] as? Float {
println("Ratio: \(ratio)")
return tableView.bounds.size.width / CGFloat(ratio)
} else {
return 50.0
}
}
Using Parse 1.11 with iOS 9.2 and Xcode 7.2 Parse Pagination works perfectly.
Problems surface when the user override some funcs used by Parse itself without properly managing the "Load More ..." row added by Parse.
In my case I needed to override tableView-canEditRowAtIndexPath to determine whether the current user can or cannot delete the row according to the object's ACL.
My initial func was:
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
if let curUser = PFUser.currentUser() {
let currentObject = objects![indexPath.row]
if let acl = currentObject.ACL {
return acl.getWriteAccessForUser(curUser)
} else {
return true
}
}
return true
}
but I got the exception of indexpath out of bounds when the Load More line was met during list scrolling.
Problem was solved adding this test:
if (indexPath.row == self.objects!.count) { // row "Load More ..."
return true
}
Without this code the "Load More ..." row was not added by Parse!!
So the complete correct overriding func is:
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
if (indexPath.row == self.objects!.count) { // row "Load More ..."
return true
}
if let curUser = PFUser.currentUser() {
let currentObject = objects![indexPath.row]
if let acl = currentObject.ACL {
return acl.getWriteAccessForUser(curUser)
} else {
return true
}
}
return true
}
Generally speaking all overridden funcs including heightForRowAtIndexpath, must take care of the extra line added by Parse when pagination is enabled.
HTH
Roberto Targa
I have a UITableViewController:
class MyMenuTableViewController: UITableViewController, UITableViewDataSource, UITableViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
}
func updateFirstMenuRow() {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
println("tableview is \(self.tableView)")
var indexPath = NSIndexPath(forRow: 0, inSection: 0)
var cell = self.tableView.cellForRowAtIndexPath(indexPath)
var rand = arc4random()
cell!.textLabel!.text = "\(rand)"
cell!.setNeedsLayout()
cell!.setNeedsDisplay()
println("cell is \(cell)")
println("rand is \(rand)")
println("textLabel.text is \(cell!.textLabel!.text!)")
})
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// Return the number of sections.
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Return the number of rows in the section.
return 3
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("CELL") as? UITableViewCell
if (cell == nil) {
cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "CELL")
}
switch indexPath.row {
case 0:
cell!.textLabel?.text = "This is the old text"
case 1:
cell!.textLabel?.text = "Foo"
case 2:
cell!.textLabel?.text = "Bar"
default:
cell!.textLabel?.text = "UNDEFINED"
}
return cell!
}
}
Note that I have a function updateFirstMenuRow() where I'll update the textLabel.text of the first tableView row with a different value (in my text case, a different number).
I need to run updateFirstMenuRow() from another class, like below:
class MyOtherClass:UIViewController{
override func viewDidLoad() {
super.viewDidLoad()
MyMenuTableViewController().updateFirstMenuRow()
}
//.....
}
It will show all println in the console, however it does not update the the cell.textLabel.text with a random number.
In console, I can see that:
tableView is NOT nil
cell is NOT nil
rand is always a different random number
textLabel.text returns (strangely enough) the always updated random number (rand)
However, the actual textLabel.text in the MyMenuTableViewController is never updated, and stays at it's initial value, "This is the old text".
When I try to run updateFirstMenuRow() within UITableViewController, it will work - meaning, it will update the textLabel.text of the first row in the tableView:
class MyMenuTableViewController: UITableViewController, UITableViewDataSource, UITableViewDelegate {
override func viewDidAppear(animated: Bool) {
updateFirstMenuRow()
}
}
Note that I'm trying to run the update functions from the main thread, as suggested by other stackoverflow questions. However, no success.
I have been struggling with this for several hours now, I'd be glad if anyone can give me some pointers as for why my update function will not properly run - my guess is that it doesn't have "write access" to the tableView in MyMenuTableViewController. Thanks a lot in advance!
This
MyMenuTableViewController().updateFirstMenuRow()
creates a new instance of MyMenuTableViewController - so the method is executed on an instance that isn't on screen. This is why you see the output of the println but no change in the tableview.
You need to pass a reference to the MyMenuTableViewController instance to the MyOtherClass instance. You need to add a property to MyOtherClass to hold the reference -
menuTableViewController:MyMenuTableViewController?
You don't show how you get from one to the other, but, for example if it was via a segue you would use the following -
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if (segue.identifier == "someIdentifier") {
let destinationVC = segue.destinationViewController as MyOtherClass
destinationVC.menuTableViewController = self
}
}
Then in your MyOtherClass you can say -
if (self.menuTableViewController != nil) {
self.menuTableViewController!.updateFirstMenuRow()
}
I managed to solve my problem thanks to Paul's answer.
I am in fact using a delegate, which is triggered in the MyOtherClass, to "forward" the command to update the textLabel.text - however, I managed to get the correct reference.
Before, I was using MyMenuTableViewController() twice
Now I am using var menuTableViewController:MyMenuTableViewController?, then I set the value once with self.menuTableViewController = MyMenuTableViewController() and then subsequently I use menuTableViewController! or menuTableViewController!.updateFirstMenuRow(), so I always update the tableView in the "same" instance of MyMenuTableViewController.
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.