unexpectedly found nil while unwrapping an Optional value in uitableviewcontroller - ios

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.

Related

TableView loop through all cell for deleting them, Swift

I was trying iterating through all cell in TableView and delete them. I call function DeleteAll:
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var myTableView: UITableView!
#IBAction func DeleteAll(sender: UIButton) {
//myTableView.reloadData()
for j in 0..<myTableView.numberOfSections {
for i in (myTableView.numberOfRowsInSection(j) - 1).stride(through: 0, by: -1) {
let myIndexPath = NSIndexPath(forRow: i, inSection: j)
print("I=" + String(i) + "section " + String(j))
self.tableView( myTableView, commitEditingStyle: UITableViewCellEditingStyle.Delete, forRowAtIndexPath: myIndexPath)
}
}
}
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.
}
var indexPathForSelectedRows = [NSIndexPath]()
lazy var productLines: [ProductLine] = {
return ProductLine.productLines()
}()
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
let selctedRow = tableView.cellForRowAtIndexPath(indexPath)!
if editingStyle == UITableViewCellEditingStyle.Delete {
productLines[indexPath.section].products.removeAtIndex(indexPath.row)
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
selctedRow.accessoryType = UITableViewCellAccessoryType.None
}
}
func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
let delete = UITableViewRowAction(style: .Destructive, title: "Delete") { (action, indexPath) in
self.tableView( tableView, commitEditingStyle: UITableViewCellEditingStyle.Delete, forRowAtIndexPath: indexPath)
}
let share = UITableViewRowAction(style: .Normal, title: "Disable") { (action, indexPath) in
}
delete.backgroundColor = UIColor.blackColor()
share.backgroundColor = UIColor.blueColor()
return [delete, share]
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
//self.tableView( tableView, commitEditingStyle: UITableViewCellEditingStyle.Delete, forRowAtIndexPath: indexPath)
let row = tableView.cellForRowAtIndexPath(indexPath)!
if row.accessoryType == UITableViewCellAccessoryType.None {
row.accessoryType = UITableViewCellAccessoryType.Checkmark
}
else {
row.accessoryType = UITableViewCellAccessoryType.None
}
}
// MARK: - Table view data source
func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
let productLine = productLines[section]
return productLine.name
}
//override func tableV
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return productLines.count
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
let productLine = productLines[section]
return productLine.products.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("uppercaseString", forIndexPath: indexPath)
let productLine = productLines[indexPath.section]
let product = productLine.products[indexPath.row]
cell.textLabel?.text = product.title
cell.detailTextLabel?.text = product.description
cell.imageView?.image = product.image
// Configure the cell...
return cell
}
}
But I have had this error, and I don't find out what wrong. This is console log:
I=3section 0
I=2section 0
I=1section 0
I=0section 0
I=8section 1
fatal error: unexpectedly found nil while unwrapping an Optional
value (lldb)
Yes, that will return nil if the row isn't on screen, so force
unwrapping is a bad idea. In fact calling the delegate methods
yourself is a bad idea. If you want to reuse code then you should have
your delegate method calla delete method. You can't retrieve all
cells; you can only retrieve cells that are onscreen. You shouldn't
need to retrieve all cells; you simply update your data model and have
the table reflect those changes by reloading the table, reloading
specific rows or inserting/deleting specific rows
– Paulw11

After reordering cell is behind another cell

I'm trying to create a reorder indicator. So what I'm trying to do is that when the user is dragging the cell. That on the place the user wants to drop the cell an other cell is added with a background. I already achieved that. But when the user drops the cell, the indicator cell needs to be deleted and the table must stay the same like the user intended to.
Now I have the following problem. When the user drops the cell. The indicator cell is correctly removed but the dropped cell is behind another cell suddenly.
Screenshots to clarify:
My code:
import UIKit
import PureLayout
class ViewController: UIViewController {
lazy var tableView: UITableView = {
let tableView = UITableView(forAutoLayout: ())
tableView.delegate = self
tableView.dataSource = self
tableView.separatorStyle = .SingleLine
tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "Default")
tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "Indicator")
tableView.tableFooterView = UIView()
return tableView
}()
private var data: [Int] = [Int]()
private var isIndicatorRowAddedInSection: Bool = false
private var lastIndicatorRowIndexPath: NSIndexPath?
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(self.tableView)
self.tableView.autoPinEdgesToSuperviewEdgesWithInsets(UIEdgeInsetsZero, excludingEdge: .Top)
self.tableView.autoPinEdgeToSuperviewEdge(.Top, withInset: 40)
for index in 0..<20 {
data.append(index)
}
self.tableView.editing = true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
extension ViewController: UITableViewDelegate {
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 44
}
func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
}
func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
if let lastIndexPath = self.lastIndicatorRowIndexPath {
print("Need to delete a row on section \(lastIndexPath.section) row \(lastIndexPath.row)")
self.isIndicatorRowAddedInSection = false
self.lastIndicatorRowIndexPath = nil
tableView.beginUpdates()
tableView.deleteRowsAtIndexPaths([lastIndexPath], withRowAnimation: .Fade)
tableView.endUpdates()
}
let itemToMove = self.data[fromIndexPath.row]
self.data.removeAtIndex(fromIndexPath.row)
self.data.insert(itemToMove, atIndex: toIndexPath.row)
}
func tableView(tableView: UITableView, editingStyleForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCellEditingStyle {
return .None
}
func tableView(tableView: UITableView, shouldIndentWhileEditingRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return false
}
func tableView(tableView: UITableView, targetIndexPathForMoveFromRowAtIndexPath sourceIndexPath: NSIndexPath,
toProposedIndexPath proposedDestinationIndexPath: NSIndexPath) -> NSIndexPath {
if let lastIndexPath = self.lastIndicatorRowIndexPath {
print("Target indexpath indexpath to delete row \(lastIndexPath.section) row \(lastIndexPath.row)")
self.isIndicatorRowAddedInSection = false
tableView.beginUpdates()
tableView.deleteRowsAtIndexPaths([lastIndexPath], withRowAnimation: .Fade)
tableView.endUpdates()
self.lastIndicatorRowIndexPath = nil
}
self.isIndicatorRowAddedInSection = true
self.lastIndicatorRowIndexPath = proposedDestinationIndexPath
tableView.beginUpdates()
print("Indicator view inserted at section \(proposedDestinationIndexPath.section) row \(proposedDestinationIndexPath.row)")
tableView.insertRowsAtIndexPaths([NSIndexPath(forRow: proposedDestinationIndexPath.row, inSection: proposedDestinationIndexPath.section)], withRowAnimation: .Automatic)
tableView.endUpdates()
return proposedDestinationIndexPath
}
}
extension ViewController: UITableViewDataSource {
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if self.isIndicatorRowAddedInSection {
return self.data.count + 1
}
return self.data.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if let indicatorIndexPath = self.lastIndicatorRowIndexPath where isIndicatorRowAddedInSection {
if indicatorIndexPath.section == indexPath.section && indicatorIndexPath.row == indexPath.row {
let cell = tableView.dequeueReusableCellWithIdentifier("Indicator", forIndexPath: indexPath)
return cell
}
}
let cell = tableView.dequeueReusableCellWithIdentifier("Default", forIndexPath: indexPath)
cell.textLabel?.text = String(self.data[indexPath.row])
return cell
}
}
I don't see the problem. Can someone help me?
I found the problem. In the moveRow it is executed on Thread 1 (main thread) but it seems like it's not. Because when you wrap it with a dispatch async to the main thread it just works.
Full working code:
import UIKit
import PureLayout
class ViewController: UIViewController {
lazy var tableView: UITableView = {
let tableView = UITableView(forAutoLayout: ())
tableView.delegate = self
tableView.dataSource = self
tableView.separatorStyle = .SingleLine
tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "Default")
tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "Indicator")
tableView.tableFooterView = UIView()
return tableView
}()
private var data: [Int] = [Int]()
private var isIndicatorRowAddedInSection: Bool = false
private var lastIndicatorRowIndexPath: NSIndexPath?
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(self.tableView)
self.tableView.autoPinEdgesToSuperviewEdgesWithInsets(UIEdgeInsetsZero, excludingEdge: .Top)
self.tableView.autoPinEdgeToSuperviewEdge(.Top, withInset: 40)
for index in 0..<5 {
data.append(index)
}
self.tableView.editing = true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
extension ViewController: UITableViewDelegate {
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 44
}
func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
}
func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
let itemToMove = self.data[fromIndexPath.row]
self.data.removeAtIndex(fromIndexPath.row)
self.data.insert(itemToMove, atIndex: toIndexPath.row - 1)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
if let lastIndexPath = self.lastIndicatorRowIndexPath {
print("Need to delete a row on section \(lastIndexPath.section) row \(lastIndexPath.row)")
self.isIndicatorRowAddedInSection = false
self.lastIndicatorRowIndexPath = nil
tableView.beginUpdates()
// Need to put some logic if you pull to top it has to be + 1
tableView.deleteRowsAtIndexPaths([NSIndexPath(forRow: lastIndexPath.row - 1, inSection: 0)], withRowAnimation: .Fade)
tableView.endUpdates()
}
})
}
func tableView(tableView: UITableView, editingStyleForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCellEditingStyle {
return .None
}
func tableView(tableView: UITableView, shouldIndentWhileEditingRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return false
}
func tableView(tableView: UITableView, targetIndexPathForMoveFromRowAtIndexPath sourceIndexPath: NSIndexPath,
toProposedIndexPath proposedDestinationIndexPath: NSIndexPath) -> NSIndexPath {
if let lastIndexPath = self.lastIndicatorRowIndexPath {
print("Target indexpath indexpath to delete row \(lastIndexPath.section) row \(lastIndexPath.row)")
self.isIndicatorRowAddedInSection = false
tableView.beginUpdates()
tableView.deleteRowsAtIndexPaths([lastIndexPath], withRowAnimation: .None)
tableView.endUpdates()
self.lastIndicatorRowIndexPath = nil
}
self.isIndicatorRowAddedInSection = true
self.lastIndicatorRowIndexPath = proposedDestinationIndexPath
tableView.beginUpdates()
print("Indicator view inserted at section \(proposedDestinationIndexPath.section) row \(proposedDestinationIndexPath.row)")
tableView.insertRowsAtIndexPaths([NSIndexPath(forRow: proposedDestinationIndexPath.row, inSection: proposedDestinationIndexPath.section)], withRowAnimation: .Automatic)
tableView.endUpdates()
return proposedDestinationIndexPath
}
}
extension ViewController: UITableViewDataSource {
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if self.isIndicatorRowAddedInSection {
return self.data.count + 1
}
return self.data.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if let indicatorIndexPath = self.lastIndicatorRowIndexPath where isIndicatorRowAddedInSection {
if indicatorIndexPath.section == indexPath.section && indicatorIndexPath.row == indexPath.row {
let cell = tableView.dequeueReusableCellWithIdentifier("Indicator", forIndexPath: indexPath)
cell.textLabel?.text = "IndicatorView: ROW \(indexPath.row) SECTION = \(indexPath.section)"
print("Indictorview cell for row")
return cell
}
}
let cell = tableView.dequeueReusableCellWithIdentifier("Default", forIndexPath: indexPath)
cell.textLabel?.text = "ROW = \(indexPath.row) SECTION = \(indexPath.section)"
return cell
}
}

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.

Why when I delete a row in a tableview it deletes multiple rows?

I'm making a notes app and added the swipe to delete a row method. The problem I'm having is when there is multiple notes saved in the table view and I go to swipe one row to delete it deletes all the notes. Also when I quit the app and go back the notes are back in the table view. Heres the code I have:
class MasterViewController: UITableViewController {
var notesItems: NSMutableArray = NSMutableArray()
override func viewDidAppear(animated: Bool) {
let userDefaults:NSUserDefaults = NSUserDefaults.standardUserDefaults()
let itemListFromUserDefaults:NSMutableArray? = userDefaults.objectForKey("itemList") as? NSMutableArray
if ((itemListFromUserDefaults) != nil) {
notesItems = itemListFromUserDefaults!
}
self.tableView.reloadData()
}
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.setNavigationBarHidden(false, animated: true)
self.navigationController?.toolbarHidden = false
self.tableView.dataSource = self
UINavigationBar.appearance().barTintColor = UIColor.orangeColor()
UIToolbar.appearance().barTintColor = UIColor.orangeColor()
}
override func numberOfSectionsInTableView(tableView: UITableView?) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return notesItems.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
let notesItem:NSDictionary = notesItems.objectAtIndex(indexPath.row) as! NSDictionary
cell.textLabel?.text = notesItem.objectForKey("text") as? String
return cell
}
// Override to support editing the table view.
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == UITableViewCellEditingStyle.Delete {
self.tableView.reloadData()
self.tableView.beginUpdates()
self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
// Delete the row from the data source
}
}
}
Your code in commitEditingStyle is all wrong.
Don't reload the table view.
You must update the database before calling deleteRowsAtIndexPaths.
You don't need to call beginUpdates/endUpdated to make one call to deleteRowsAtIndexPaths.
You want:
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == UITableViewCellEditingStyle.Delete {
// remove an object from notesItem for this index path
self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
}
}

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