Swift - Save checkmarks selected in TableView

倖福魔咒の 提交于 2019-12-05 02:21:02

问题


I am fairly new to Swift and I am having an issue on TableView multi-selection. I have multiple selections that I can check with a checkmark, similar to to-do list.

When I check the items I want to be able to come back to the ListView and have my selections saved. I'm assuming that the code to keep this in saved state would go somewhere here? This is the class where the individual cell item checkmark is written :

    class ListItem: NSObject {
    let itemName: String
    var completed: Bool

    init(itemName: String, completed: Bool = false)
    {
        self.itemName = itemName
        self.completed = completed
    }
}   

Can Someone please show me how to go about this?

This is the cellForRowAtIndexPath

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let tempCell = tableView.dequeueReusableCellWithIdentifier("ListPrototypeCell") as UITableViewCell
    let listItem = listItems[indexPath.row]

    // Downcast from UILabel? to UILabel
    let cell = tempCell.textLabel as UILabel!
    cell.text = listItem.itemName

    if (listItem.completed)
    {
        tempCell.accessoryType = UITableViewCellAccessoryType.Checkmark;
    }
    else
    {
        tempCell.accessoryType = UITableViewCellAccessoryType.None;
    }

    return tempCell
}    

and my didSelectRowAtIndexPath

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    tableView.deselectRowAtIndexPath(indexPath, animated: false)

    let tappedItem = listItems[indexPath.row] as ListItem
    tappedItem.completed = !tappedItem.completed

    tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.None)

}    

回答1:


Two things:

Your code in cellForRowAtIndexPath: is perfect. It takes the info from listItems[indexPath.row] to populate your cell's text and checkmark. But in your didSelectRowAtIndexPath:, you never change listItems such that cellForRowAtIndexPath: has the updated data from which to pull the new row upon reload. So instead of using deselectRowAtIndexPath:, simply update the listItems array then reloadRowsAtIndexPaths. (Honestly, I'm confused as to why it was working for you up to this point since you were calling reload on un-updated data.) Here's what I recommend:

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

    let tappedItem = listItems[indexPath.row] as ListItem
    tappedItem.completed = !tappedItem.completed

    // Store the updated tappedItem back at the listItems index
    listItems[indexPath.row] = tappedItem

    tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.None)

}

Secondly, as long as that array is being stored in a view controller that's not being deallocated, you won't lose that data and you'll be able to repopulate the table. But if it's being stored in a view controller (or table view controller) that's being deallocated, you may want to store it elsewhere in your program.




回答2:


I presume you have an array of ListItem representing the model data (the contents of the table view). Then to preserve this outside the running app you can save it off into NSUserDefaults or into a file. To do so, you will need a way of serializing a ListItem. The usual way to do this is to have ListItem adopt the NSCoding protocol and implement encodeWithCoder: and init(coder:) to use NSKeyedArchiver and NSKeyedUnarchiver (the "coder" in those methods) to turn a ListItem object into an NSData and vice versa. Once you've done that, an array of ListItem can be directly serialized with NSKeyedArchiver and NSKeyedUnarchiver.




回答3:


Solved this mixing and matching a bit, using NSUserDefaults Here it goes:

Created a button in the navigation bar of my pop-over Table/ListView and functionalities to the button:

 //create a done button in the navigation bar
    var done = UIBarButtonItem(title: "Done", style: .Plain, target: self, action: Selector("doneBtn"))
    self.navigationItem.rightBarButtonItem = done

}

//This is the "Done" button functionality

func doneBtn()
{

    var saveString = ""

    for var i=0; i<listItems.count; i++
    {
        let listItem = listItems[i]
        if (listItem.completed)
        {
            saveString = saveString + "  " + "\(i)"
        }
    }

    saveString = saveString.stringByTrimmingCharactersInSet(NSCharacterSet .whitespaceAndNewlineCharacterSet())

    NSUserDefaults.standardUserDefaults().setValue(saveString, forKey: "savedValues")
    NSUserDefaults.standardUserDefaults().synchronize()


    self.navigationController?.dismissViewControllerAnimated(true, completion: nil)


    }

Then in my func for loading the initial data array, which holds my list items, created a variable savedValues which looked like this:

 var savedValues : String? = NSUserDefaults.standardUserDefaults().valueForKey("savedValues") as? String



    if(!(savedValues==nil))
    {
        var nsStr: NSString = savedValues!
        let array = nsStr.componentsSeparatedByString("  ");
        for val in array {
            listItems[val.integerValue].completed = true
        }
    }

And naturally, don't forget to call loadInitialData() in your viewDidLoad()

Thank you to all that helped me out :)



来源:https://stackoverflow.com/questions/27237326/swift-save-checkmarks-selected-in-tableview

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!