TableView displaying only one cell - ios

hello I am using Dynamic Prototypes with the style Grouped. The problem is that table is not populating all the data from array. Here is the screenshot of attribute inspector
and here is my code
class ProductRequestTableViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
var profileImage = ["image1","image2"]
var userName = ["john doe","john doe"]
var requestTitle = ["lorem ipsum lorem ipsum.","I have a Wordpress website and I am looking for someone to create a landing page with links and a cart to link up"]
var date = ["Feb 03, 16","Feb 03, 16"]
func numberOfSectionsInTableView(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 profileImage.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if(indexPath.row==0){
let cell = tableView.dequeueReusableCellWithIdentifier("firstCustomCell", forIndexPath: indexPath) as! FirstProductRequestTableViewCell
cell.userNameLabel.text = userName[indexPath.row]
cell.profileImage.image = UIImage(named: profileImage[indexPath.row])
return cell
}else{
let cell = tableView.dequeueReusableCellWithIdentifier("secondCustomCell", forIndexPath: indexPath) as! SecondProductRequestTableViewCell
cell.requestTitleTxtView.text = requestTitle[indexPath.row]
return cell
}
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print(indexPath.row)
}
// Override to support conditional editing of the table view.
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.
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
// Delete the row from the data source
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
} 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 to support rearranging the table view.
func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
}
// Override to support conditional rearranging of the table view.
func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return false if you do not want the item to be re-orderable.
return true
}
What I am doing wrong here?

Related

Reordering cells in UITableView takes out functionality of cells in Swift?

I am using JSON to parse data from Spotify and add songs into a UITableView. The songs play fine, and I added functionality for deleting cells, but when adding functionality for reording cells, I can''t play songs and I can't swipe to delete them either. Any ideas would be appreciated.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.tableView.isEditing = true
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
This adds the album image and song name to the TableView.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")
let mainImageView = cell?.viewWithTag(2) as! UIImageView
mainImageView.image = posts[indexPath.row].mainImage
let mainLabel = cell?.viewWithTag(1) as! UILabel
mainLabel.text = posts[indexPath.row].name
return cell!
}
This adds the swipe to delete functionality.
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
posts.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
} 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 tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
return .none
}
override func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool {
return false
}
This adds the reordering functionality.
override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
let movedObject = self.posts[sourceIndexPath.row]
posts.remove(at: sourceIndexPath.row)
posts.insert(movedObject, at: destinationIndexPath.row)
debugPrint("\(sourceIndexPath.row) => \(destinationIndexPath.row)")
self.tableView.reloadData()
}
You don't want to set
self.tableView.isEditing = true
in viewDidLoad. This takes you from the "normal" mode where you can select a cell, or other elements in a cell. Setting "self.tableview.isEditing" is the equivalent of hitting an edit button on the top right-hand corner of many tableViews.

Can't edit/delete top row in uitableview - Swift

Not sure why but the top row of my uitableview is not editable, all other rows function as normal and delete as expected. It's like caneditrowat indexPath: Indexpath isn't working for that one row. See images attached.
My code in tableView(_:commit:forRowAt:) looks like all the tutorials I can find, can't seem to find any other examples with this problem.
//MARK: Properties
var favouriteExercises = [FavouriteExercise]()
override func viewDidLoad() {
super.viewDidLoad()
//Load exercises from local DB
if let savedFavouriteExercises = loadFavouriteExercises()
{
//loading exercises in from the favourites
favouriteExercises += savedFavouriteExercises
}
// Use the edit button item provided by the table view controller.
navigationItem.rightBarButtonItem = editButtonItem
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//count number of rows in table
return favouriteExercises.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Table view cells are reused and should be dequeued using a cell identifier.
let cellIdentifier = "FavouriteTableViewCell"
guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as? FavouriteTableViewCell else {
fatalError("The dequeued cell is not an instance of FavouriteTableViewCell.")
}
// Fetches the appropriate exercise for the data source layout.
let exercise = favouriteExercises[indexPath.row]
//setup the layout for the cell in the table view
cell.nameLabel.text = exercise.name
let url = URL(string: (exercise.iconUrl))!
cell.photoImageView.sd_setImage(with: url)
//cell.photoImageView.image = #imageLiteral(resourceName: "defaultPhoto")
cell.backgroundColor = UIColor.darkGray
return cell
}
// Override to support conditional editing of the table view.
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> 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, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// Delete the row from the data source
favouriteExercises.remove(at: indexPath.row)
saveFavouriteExercisess()
tableView.deleteRows(at: [indexPath], with: .fade)
}
}
Thanks for the help
override func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle
{
return UITableViewCellEditingStyle.delete
}
Answer adapted from #KumarReddy's solution

Swift static tableview with dynamic section

I have tableviewcontroller, with 2 sections.
First(static) section have 2 rows, and second section should be dynamic.
Storyboard:
Code:
class DocumentInventoryChangeTableViewController: UITableViewController {
var results: [String] = ["Dog", "Cat", "Snake", "Test"]
override func viewDidLoad() {
super.viewDidLoad()
tableView.registerNib(UINib(nibName: "DocumentInventoryCell", bundle: nil), forCellReuseIdentifier: "DocumentInventoryCell")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 2
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 1 {
return results.count
}
return 2
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell: UITableViewCell!
if indexPath.section == 0 {
cell = super.tableView(tableView, cellForRowAtIndexPath: indexPath)
} else {
cell = tableView.dequeueReusableCellWithIdentifier("DocumentInventoryCell", forIndexPath: indexPath)
cell.textLabel?.text = results[indexPath.row]
}
return cell
}
}
But i'm getting this error:
Terminating app due to uncaught exception 'NSRangeException', reason:
'*** -[__NSArray0 objectAtIndex:]: index 0 beyond bounds for empty
NSArray'
In my experience, it was enough to override these methods in UITableViewController:
tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
tableView(tableView: UITableView, indentationLevelForRowAtIndexPath indexPath: NSIndexPath) -> Int
If you want to have custom table view cell in your table view, you need to crate subclass of UITableViewCell also with nib, and register it to your table view.
My whole controller looks like this:
var data = ["Ahoj", "Hola", "Hello"]
override func viewDidLoad() {
super.viewDidLoad()
tableView.registerNib(UINib(nibName: "CustomCell", bundle: nil), forCellReuseIdentifier: "reuseIdentifier")
}
// MARK: - Table view data source
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 1 {
return data.count
}
return super.tableView(tableView, numberOfRowsInSection: section)
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if indexPath.section == 1 {
let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath) as! CustomCell
cell.titleLabel.text = data[indexPath.row]
return cell
}
return super.tableView(tableView, cellForRowAtIndexPath: indexPath)
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 44
}
override func tableView(tableView: UITableView, indentationLevelForRowAtIndexPath indexPath: NSIndexPath) -> Int {
return 0
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
if indexPath.section == 1 {
print(data[indexPath.row])
}
}
#IBAction func addItem() {
data.append("Item \(data.count)")
tableView.beginUpdates()
tableView.insertRowsAtIndexPaths([NSIndexPath(forRow: data.count - 1, inSection: 1)], withRowAnimation: .Left)
tableView.endUpdates()
}
#IBAction func removeItem() {
if data.count > 0 {
data.removeLast()
tableView.beginUpdates()
tableView.deleteRowsAtIndexPaths([NSIndexPath(forRow: data.count, inSection: 1)], withRowAnimation: .Left)
tableView.endUpdates()
}
}
The problem is that there is no such thing as a table view where the "First(static) section have 2 rows, and second section should be dynamic." Your table view needs to be entirely dynamic; that is, it should show a prototype cell, not static contents, in the storyboard, and its entire contents should be configured in code, including the first section — even though the first section never changes.

unexpectedly found nil while unwrapping an Optional value in uitableviewcontroller

I get this error when I actually run the code (this line is the problem var cell:UITableViewCell = tableView.dequeueReusableCellWithIdentifier(CellId) as UITableViewCell. THis is in a UITableViewController class.
import UIKit
class AlarmsTableViewController: UITableViewController {
var myData:Array<AnyObject> = []
override func viewDidLoad() {
myData = ["one", "two", "three", "four"]
}
override func didReceiveMemoryWarning() {
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return myData.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let CellId:String = "Cell"
var cell:UITableViewCell = tableView.dequeueReusableCellWithIdentifier(CellId) as UITableViewCell
//if let ip = indexPath {
cell.textLabel?.text = myData[indexPath.row] as? String
//}
return cell
}
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
//Delete row from data source
//if let tv = tableView? {
myData.removeAtIndex(indexPath.row)
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
} else if editingStyle == .Insert {
}
}
}
In the interface builder, select the TableViewController with which you are working with. Then, select the prototype cell and set its style to "Basic". Finally, set the cells reuse identifier to Cell.

How to delete TableViewCell that being a Dictionary Swift

I am trying to delete a table view cell using swipe to delete, but I can't use the line I marked in my code, not sure why. My cells are being made by a Dictionary, with the key for the title and the value for the details.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
//Create the cell by the dictionary favDict
for (key, value) in favDict{
cell.textLabel?.text = key
cell.detailTextLabel?.text = value
}
return cell
}
func tableView(tableView: UITableView!, canEditRowAtIndexPath indexPath: NSIndexPath!) -> Bool {
return true
}
func tableView(tableView: UITableView!, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath!) {
if editingStyle == UITableViewCellEditingStyle.Delete {
favDict.removeAtIndex(indexPath!.row)// Line that is giving the error says Int is not convertible for [String: String]
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
}
}
Resolution:
import UIKit
class ViewController2: UIViewController, UITableViewDelegate {
var dictKeys : [String]?
#IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
dictKeys = Array(favDict.keys)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
dictKeys = Array(favDict.keys)
return rowsInSec
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
var key = dictKeys?[indexPath.row]
var data = favDict[key!]
cell.textLabel?.text = key
cell.detailTextLabel?.text = data
return cell
}
func tableView(tableView: UITableView!, canEditRowAtIndexPath indexPath: NSIndexPath!) -> Bool {
return true
}
func tableView(tableView: UITableView!, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath!) {
if editingStyle == UITableViewCellEditingStyle.Delete
{
var key = dictKeys?[indexPath.row]
favDict.removeValueForKey(key!)
dictKeys?.removeAtIndex(indexPath.row)
rowsInSec--
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
}
}
}
You can't use;
favDict.removeAtIndex(indexPath!.row)
removeAtIndex is a instance method of NSMutableArray. For removing value from dictionary you can use:
favDict.removeValueForKey("yourkey")
EDIT:
The removing and loading data using Dictionary is little bit hard compared to NSMutableArray. Also you put a loop in the cellForRowAtIndexPath: . It'll load only the last object to every cell.
If you are still looking for Dictionary, you can do it like:
Implement the methods like:
var dictKeys : [Strings]?
override func viewDidLoad()
{
super.viewDidLoad()
dictKeys = Array(favDict.keys)
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
var key = dictKeys?[indexPath.row]
var data = favDict[key!]
cell.textLabel?.text = key
cell.detailTextLabel?.text = data
return cell
}
func tableView(tableView: UITableView!, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath!)
{
if editingStyle == UITableViewCellEditingStyle.Delete
{
var key = dictKeys?[indexPath.row]
favDict.removeValueForKey(key!)
dictKeys?.removeAtIndex(indexPath.row)
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
}
}

Resources