Ios 如何在Swift核心数据应用程序的UITableView中保存选中标记状态

Ios 如何在Swift核心数据应用程序的UITableView中保存选中标记状态,ios,swift,uitableview,core-data,nsuserdefaults,Ios,Swift,Uitableview,Core Data,Nsuserdefaults,我已经使用核心数据实现了一个列表应用程序。我想做的是添加复选标记,这样用户就可以单击单元格,并显示一个勾号以显示它已完成 我不知道如何保存这些复选标记,因此当应用程序关闭、打开或重新启动时,该复选标记仍将存在于特定单元格中。我应该使用CoreData还是NSUserDefaults来实现这一点?我将如何使用这些工具来实现它 以下是迄今为止的代码: CellForRowatinex: override func tableView(tableView: UITableView, cellForRo

我已经使用核心数据实现了一个列表应用程序。我想做的是添加复选标记,这样用户就可以单击单元格,并显示一个勾号以显示它已完成

我不知道如何保存这些复选标记,因此当应用程序关闭、打开或重新启动时,该复选标记仍将存在于特定单元格中。我应该使用CoreData还是NSUserDefaults来实现这一点?我将如何使用这些工具来实现它

以下是迄今为止的代码:

CellForRowatinex:

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

    let cell = tableView.dequeueReusableCellWithIdentifier("Cell")! as UITableViewCell
    let item = Items[indexPath.row]
    cell.textLabel?.item = task.valueForKey("item") as? String

    return cell
}
DIDSelectRowatinex:

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


    let selectedRow:UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)!

    if selectedRow.accessoryType == UITableViewCellAccessoryType.None {

        selectedRow.accessoryType = UITableViewCellAccessoryType.Checkmark

        selectedRow.tintColor = UIColor.greenColor()

    } else {

        selectedRow.accessoryType = UITableViewCellAccessoryType.None

    } 
} 

任何帮助都将不胜感激。

您需要在数据模型(核心数据对象)而不是单元格中跟踪完成状态。如您所发现的,单元格将被重复使用,并且单元格不会被持久化,因此不会保存复选标记状态

我会用这样的方式:

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

    let taskObject=self.listItems[indexPath.row]
    var taskStatus = taskObject.valueForKey("completed") as? Bool ?? false

    taskObject.setValue(!taskStatus,forKey:"completed") // Toggle completed status

    do {
        try managedContext.save()
    } catch let error as NSError {
        print("Cannot save object: \(error), \(error.localizedDescription)")
    }

    tableView.deselectRowAtIndexPath(indexPath,animated:false)

    tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .None)
}
然后,在
cellforrowatinexpath
中,可以适当地渲染行:

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

    let cell = tableView.dequeueReusableCellWithIdentifier("listCell") as! UITableViewCell
    let task = listItems[indexPath.row]
    let taskStatus = task.valueForKey("completed") as! Bool
    cell.textLabel?.text = task.valueForKey("task") as? String

    var accessoryType=UITableViewCellAccessoryType.None
    var tintColor = UIColor.clearColor()

    if (taskStatus) {
         accessoryType=UITableViewCellAccessoryType.Checkmark
         tintColor = UIColor.greenColor()
    }

    cell.accessoryType=accessoryType
    cell.tintColor = tintColor

    return cell
}

您需要在数据模型(核心数据对象)而不是单元格中跟踪完成状态。如您所发现的,单元格将被重复使用,并且单元格不会被持久化,因此不会保存复选标记状态

我会用这样的方式:

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

    let taskObject=self.listItems[indexPath.row]
    var taskStatus = taskObject.valueForKey("completed") as? Bool ?? false

    taskObject.setValue(!taskStatus,forKey:"completed") // Toggle completed status

    do {
        try managedContext.save()
    } catch let error as NSError {
        print("Cannot save object: \(error), \(error.localizedDescription)")
    }

    tableView.deselectRowAtIndexPath(indexPath,animated:false)

    tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .None)
}
然后,在
cellforrowatinexpath
中,可以适当地渲染行:

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

    let cell = tableView.dequeueReusableCellWithIdentifier("listCell") as! UITableViewCell
    let task = listItems[indexPath.row]
    let taskStatus = task.valueForKey("completed") as! Bool
    cell.textLabel?.text = task.valueForKey("task") as? String

    var accessoryType=UITableViewCellAccessoryType.None
    var tintColor = UIColor.clearColor()

    if (taskStatus) {
         accessoryType=UITableViewCellAccessoryType.Checkmark
         tintColor = UIColor.greenColor()
    }

    cell.accessoryType=accessoryType
    cell.tintColor = tintColor

    return cell
}


您的核心数据实体需要一个
已完成的
属性。任务完成后,将其设置为true并保存对象。使用此属性的值确定是否应在
cellforrowatinexpath
中的给定行中添加复选标记。好的,我现在在核心数据实体中添加了一个名为“completed”的属性,并将其设置为boolean,让我直截了当地说,我是否在didSelectRowAtIndex方法中将已完成的任务设置为true?是的。在该方法中,您将其设置为true(如果它已经为true并且您希望支持切换功能,则可能为false),然后保存对象。在该方法中,您可以添加复选标记,在cellForRowAtIndexPath中,您也可以选择completed并将附件视图设置为复选标记或none(视情况而定),以便在didSelectRow方法中使用类似“selectedRow.setValue(true,forKey:“completed”)”的内容?在代码“”中,如果在我的上述代码中selectedRow.accessoryType==UITableViewCellAccessoryType.None{}“”?Not selectedRow,则使用indexPath中的行值从
listItems
获取NSManagedObject,您的核心数据实体需要一个
completed
Arribute。任务完成后,将其设置为true并保存对象。使用此属性的值确定是否应在
cellforrowatinexpath
中的给定行中添加复选标记。好的,我现在在核心数据实体中添加了一个名为“completed”的属性,并将其设置为boolean,让我直截了当地说,我是否在didSelectRowAtIndex方法中将已完成的任务设置为true?是的。在该方法中,您将其设置为true(如果它已经为true并且您希望支持切换功能,则可能为false),然后保存对象。在该方法中,您可以添加复选标记,在cellForRowAtIndexPath中,您也可以选择completed并将附件视图设置为复选标记或none(视情况而定),以便在didSelectRow方法中使用类似“selectedRow.setValue(true,forKey:“completed”)”的内容?如果代码“”中的selectedRow.accessoryType==UITableViewCellAccessoryType.None{}在我的上述代码中?未selectedRow,您可以使用indexPath中的行值从
listItems
获取NSManagedObject,谢谢您的时间,但我在“let taskStatus=task[“completed”]as”行中收到了两个“type”NSManagedObjects“has no subscription members”错误!“CellForRow”中的Bool'和“var taskStatus=taskObject[“completed”]为!“DidSelect”中的Bool?对不起。我是凭记忆打字的。您可以使用
valueForKey[“completed”]
setValue(,forKey:)
但是如果您使用Xcode为您生成NSManagedObject子类,那么使用核心数据要容易得多。我会在
didSelect
中使用
setValue(,forKey:)
cellForRow
中使用
valueForKey
?很抱歉,我不熟悉核心数据,我想这是一个帮助我学习的入门项目,如果更容易,您是否能够使用
valueForKey
setValue
更新代码?创建新任务时,您应该将此值初始化为
false
。哪一行通过nil异常?它是
让taskStatus=task.valueForKey(“已完成”)作为!Bool
line in
CellForRow
谢谢您的时间,但我收到了两个错误,分别是“类型”NSManagedObjects“没有订阅成员”和“行”let taskStatus=task[“已完成”]as!“CellForRow”中的Bool'和“var taskStatus=taskObject[“completed”]为!“DidSelect”中的Bool?对不起。我是凭记忆打字的。您可以使用
valueForKey[“completed”]
setValue(,forKey:)
但是如果您使用Xcode为您生成NSManagedObject子类,那么使用核心数据要容易得多。我会在
didSelect
中使用
setValue(,forKey:)
cellForRow
中使用
valueForKey
?很抱歉,我不熟悉核心数据,我想这是一个帮助我学习的入门项目,如果更容易,您是否能够使用
valueForKey
setValue
更新代码?创建新任务时,您应该将此值初始化为
false
。哪一行通过nil异常?它是
让taskStatus=task.valueForKey(“已完成”)作为!Bool
行在
CellForRow