Error when trying to save to NSUserdefaults

与世无争的帅哥 提交于 2019-12-01 08:40:18

I don't know why you are saving all the NSIndexPath's for the cells selected previously when according your previous question and this one, you need to save only the index of the cell selected and the value of the total you had when you go to another controller. You can do it in the following way:

var frequency = [
    Item(name:"Every week",selected: false, amount: 30),
    Item(name:"Every 2 weeks",selected: false, amount: 30),
    Item(name:"Every 4 weeks",selected: false, amount: 30),
    Item(name:"Once",selected: false, amount: 40),
    Item(name:"End of tenancy cleaning", selected: false, amount: 44)
]

var indexPathForCellSelected: NSIndexPath?
var total = 0

let indexPathKey = "indexPathForCellSelectedNinethViewControllerKey"
let totalKey = "totalNinethViewControllerKey"

override func viewDidLoad() {
    super.viewDidLoad()

    loadData()
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
    cell.textLabel?.text = frequency[indexPath.row].name
    if let _ = indexPathForCellSelected where indexPath == indexPathForCellSelected {
        cell.accessoryType = .Checkmark
    }
    return cell
}

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

    if !frequency[indexPath.row].selected {

        // this avoid set initial value for the first time
        if let index = indexPathForCellSelected {
            // clear the previous cell
            frequency[index.row].selected = false
            tableView.cellForRowAtIndexPath(index)?.accessoryType = .None
            self.total -= frequency[index.row].amount
        }

        // mark the new one
        frequency[indexPath.row].selected = true
        tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = .Checkmark

        indexPathForCellSelected = indexPath
        self.total += frequency[indexPath.row].amount

        saveData()
    }
}

private func saveData() {

    // save the index for the cell selected in NSUserDefaults
    NSUserDefaults.standardUserDefaults().setInteger(indexPathForCellSelected!.row, forKey: indexPathKey)

    // save total in NSUserDefaults
    NSUserDefaults.standardUserDefaults().setInteger(total, forKey: totalKey)
}

private func loadData() {

    // get the values from NSUserDefaults if exist
    if let indexValue = NSUserDefaults.standardUserDefaults().valueForKey(indexPathKey), totalValue = NSUserDefaults.standardUserDefaults().valueForKey(totalKey) {
        indexPathForCellSelected = NSIndexPath(forRow: indexValue as! Int, inSection: 0)
        total = totalValue as! Int
    }
}

I hope this help you.

Try putting an expression to add the checkmark in the tableView(_:didSelectRowAtIndexPath:) function, where you should also be able to implement the adding and subtracting based on its state. So you could do something like this:

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        if let cell = tableView.cellForRowAtIndexPath(indexPath) {
            if cell.accessoryType == .None {
                cell.accessoryType = .Checkmark
                total += extras[indexPath.row].amount
            } else if cell.accessoryType == .Checkmark {
                cell.accessoryType = .None
                total -= extras[indexPath.row].amount
            }
            // Call function to save here
        }
    }

This is the correct answer to my question. If anyone has a better approach, post your version in the answer section.

class NinethViewController: UIViewController, UITableViewDelegate,UITableViewDataSource {
var total = 0
var totalKey = "totalNinethViewControllerKey"
let indexPathKey = "indexPathForCellSelectedNinethViewControllerKey"
var indexPathsForCellSelected: NSMutableSet = NSMutableSet()// {NSIndexPath}


struct Item {
    var name:String // name of the row
    var selected:Bool // whether is selected or not
    var amount: Int // value of the item
}

var extras = [

    Item(name:"Inside Cabinets",selected: false, amount: 5),
    Item(name:"Inside Fridge",selected: false, amount: 5),
    Item(name:"Inside Oven",selected: false, amount: 5),
    Item(name:"Laundry wash & dry",selected: false, amount: 10),
    Item(name:"Interior Windows", selected: false, amount: 5)
]


@IBOutlet weak var tableView: UITableView!

override func viewDidLoad() {
    super.viewDidLoad()
}

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

    // loadData from NSUserDefaults
    self.loadData()

}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return extras.count
}

func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
}

// configure the cell
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath)
    -> UITableViewCell     {
        let cell = tableView.dequeueReusableCellWithIdentifier("Cell")
        cell?.textLabel?.text = extras[indexPath.row].name
        return cell!
}

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

    // if the cell has not been selected before
    if !extras[indexPath.row].selected {

        // marks the cell as selected once
        extras[indexPath.row].selected = true
        tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = .Checkmark
        self.total += extras[indexPath.row].amount

        indexPathsForCellSelected.addObject(indexPath)


        print("selecting")
        print(total)



    } else {
        // marks the cell as not selected
        extras[indexPath.row].selected = false
        tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = .None
        self.total -= extras[indexPath.row].amount

        indexPathsForCellSelected.removeObject(indexPath)
        print(total)
    }
     //   save all info in NSUserDefaults
    self.saveData()
}

func saveData() {
    // save indexPathsForCellSelected in NSUserDefaults
    let data = NSKeyedArchiver.archivedDataWithRootObject(indexPathsForCellSelected)
    NSUserDefaults.standardUserDefaults().setObject(data, forKey: indexPathKey)

    //save total in NSUserDefaults
    NSUserDefaults.standardUserDefaults().setObject(total, forKey: totalKey)
}

func loadData() {
    //retrieve indexPathForCellSelected from NSUserDefaults
 if let retrievedIndexPath = NSUserDefaults.standardUserDefaults().dataForKey(indexPathKey) {
        if let data1 = NSKeyedUnarchiver.unarchiveObjectWithData(retrievedIndexPath) as? NSMutableSet{
            indexPathsForCellSelected = data1
        }
    }

    // assign checkmark to row selected
    for item in indexPathsForCellSelected {

        if let indexPath = item as? NSIndexPath {
            extras[indexPath.row].selected = true
                self.tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = .Checkmark

            /* let tableV = self.tableView
            let cell = tableV.cellForRowAtIndexPath(indexPath)
            extras[indexPath.row].selected = true
            cell?.accessoryType = .Checkmark  */

        }
    }

    // retrieve total from NSUserDefaults
    if let totalRetrieved = NSUserDefaults.standardUserDefaults().objectForKey(totalKey) as? Int {
        total = totalRetrieved
        print(total)
    }
}
}

Try to synchronize the NSUserDefaults after setting the data.

let defaults = NSUserDefaults.standardUserDefaults()

defaults.setObject("1", forKey: "SomeKey")
defaults.synchronize() // Sync the defaults to update the data
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!