在看似随机的列表位置插入 CoreData 对象
Posted
技术标签:
【中文标题】在看似随机的列表位置插入 CoreData 对象【英文标题】:CoreData Object Inserted at Seemingly Random List Position 【发布时间】:2015-08-20 22:46:18 【问题描述】:我在单独的视图中有两个表,每个表的列表在 CoreData 中都有一个单独的实体。用户可以点击任何单元格中的按钮将其移动到另一个列表。这很有效,只需点击一下即可移动项目,所有内容都会在应用关闭后保存并持续存在。
问题
目前,代码应该计算目标列表中的项目,然后将要移动的项目附加到其新列表的末尾。这不会发生。相反,该项目是随机插入的(不是在末尾或开头)。但是,一旦它被插入,任何进一步的移动项目都将直接位于它的下方。我尝试用 1 替换 count 函数,因为我真的希望移动的项目无论如何都显示在顶部,但这无济于事。
代码
首先,这是每次主视图出现时运行加载主列表的 viewDidLoad 代码:
override func viewDidLoad()
super.viewDidLoad()
currentListEntity = curList
//Load the list from Core Data
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext!
let fetchRequest = NSFetchRequest(entityName: currentListEntity)
let sortDescriptor = NSSortDescriptor(key: "displayOrder", ascending: true )
fetchRequest.sortDescriptors = [ sortDescriptor ]
var error: NSError?
let fetchedResults = managedContext.executeFetchRequest(fetchRequest, error: &error) as? [NSManagedObject]
if let results = fetchedResults
taskList_Cntxt = results
else
println("Could not fetch \(error), \(error!.userInfo)")
我希望将移动的对象附加到新列表的末尾(这是实体参数)的功能,而是将其插入到其他列表项中:
func addToList (sender: AnyObject, entity: String)
//Setup CoreData context
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext!
let entity = NSEntityDescription.entityForName(entity, inManagedObjectContext: managedContext)
let task = NSManagedObject(entity: entity!, insertIntoManagedObjectContext:managedContext)
//Figure out the cell pressed
let button = sender as! UIButton
let contentView = button.superview!
let cell = contentView.superview as! CustomTableViewCell_F2
//Set cell contents to variables
var nameValue = cell.nameLabel!.text
var descValue = cell.descLabel!.text
//Set content variables to NSObject called "task"
task.setValue(nameValue, forKey: "name")
task.setValue(descValue, forKey: "desc")
//Error check
var error: NSError?
if !managedContext.save(&error)
println("Could not save \(error), \(error?.userInfo)")
//Get count, append to end, sort, save
var insertAt = taskList_Cntxt.count
addTask(task, displayOrder: insertAt)
updateDisplayOrder()
managedContext.save(nil)
//Referenced by larger add-task function
func addTask( task: NSManagedObject, displayOrder: Int )
taskList_Cntxt.insert( task, atIndex: displayOrder )
updateDisplayOrder()
//Called to update Core Data after append, delete, and drag/drop
func updateDisplayOrder()
for i in 0..<taskList_Cntxt.count
let task = taskList_Cntxt[i]
task.setValue( i, forKey: "displayOrder" )
关于如何解决这个问题的任何想法?理想情况下附加到列表的顶部,但此时将其附加到底部也很好。
【问题讨论】:
您似乎正在将任务添加到您的函数addTask
中的列表中,而您没有包括该列表。另外updateDisplayOrder
听起来肯定会影响显示顺序,但也不包括在内。几乎可以肯定,这两者对于正确订购都至关重要。
@TomHarrington 很抱歉,在熬夜后发布了这篇文章,试图解决这个问题和另一个问题,显然需要睡觉!我已经包含了这两个函数
【参考方案1】:
我终于弄明白了!
之前,当我使用该应用程序并查看列表并点击“移动到 x 列表”以获取项目时,该项目将被添加到中间某处的目标列表中。
现在,在修复它之后,将任务从一个列表添加到另一个列表效果很好,当我加载目标列表时,我发送的项目始终位于顶部。
解决方案
如果您查看我的代码,我实际上所做的是提供了错误的插入地址。错误出现在两个地方。
错误 1
我正在获取旧列表的计数并将计数用作我的插入位置:
//Get count, append to end, sort, save
var insertAt = taskList_Cntxt.count
addTask(task, displayOrder: insertAt)
updateDisplayOrder()
managedContext.save(nil)
现在我已将方法更改为始终在 1 处插入:
var insertAt = 1
addTask(task, displayOrder: insertAt)
update_TargetDisplayOrder()
managedContext.save(nil)
错误 2
当我重新编号列表时,我更新了错误的列表:
func updateDisplayOrder()
for i in 0..<taskList_Cntxt.count
let task = taskList_Cntxt[i]
task.setValue( i, forKey: "displayOrder" )
现在我将我的 add 函数指向一个查看目标列表而不是源列表的更新方法:
func update_TargetDisplayOrder()
for i in 0..<targetList_Cntxt.count
let task = targetList_Cntxt[i]
task.setValue( i, forKey: "displayOrder" )
为了做到这一点,我需要添加第二个上下文变量。添加 targetList_Cntxt 允许我重新排序新列表而不是旧列表。在我这样做之后,一切正常。
注意:
添加功能运行后,该项目从旧列表中删除:
func codeForDelete(sender: AnyObject)
//Figure out the cell pressed
let cell = sender as! CustomTableViewCell
let indexPath = tableView.indexPathForCell(cell)
//Setup variables for CoreData delete methods
let appDel: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let context: NSManagedObjectContext = appDel.managedObjectContext!
//Remove the deleted item from the model
context.deleteObject(taskList_Cntxt[indexPath!.row] as NSManagedObject)
taskList_Cntxt.removeAtIndex(indexPath!.row)
context.save(nil)
viewDidLoad()
println("Delete task function ran")
但是当我写这篇文章时,我意识到我遗漏了一个函数来更新旧列表的排序顺序,一旦我执行删除。这是我可能需要解决的问题!
【讨论】:
以上是关于在看似随机的列表位置插入 CoreData 对象的主要内容,如果未能解决你的问题,请参考以下文章
Core Data 中看似有效的对象出现“悬空引用无效对象”错误