CoreData 对象插入看似随机的列表位置
CoreData Object Inserted at Seemingly Random List Position
我在不同的视图中有两个 table,每个 table 的列表在 CoreData 中都有一个单独的实体。用户可以点击任何单元格内的按钮将其移动到另一个列表。这行得通,只需轻按一下即可移动项目,所有内容都会保存并在应用程序关闭后保留。
问题
目前代码应该对目标列表中的项目进行计数,然后将要移动的项目追加到其新列表的末尾。这不会发生。相反,该项目是随机插入的(不是在末尾或开头)。但是,一旦插入,任何进一步移动的项目都将直接位于其下方。我尝试用 1 替换计数函数,因为我真的希望移动的项目无论如何都显示在顶部,但这没有帮助。
代码
首先,这是每次主视图出现时运行加载主列表的 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" )
}
}
关于如何解决这个问题有什么想法吗?理想情况下附加到列表的顶部,但此时将它附加到底部也很好。
我终于弄明白了!
在之前,当我使用该应用程序并查看列表并点击 'move to x list' 获取某个项目时,该项目将被添加到目标列表中的某处中间。
现在,在修复它后,将一个任务从一个列表添加到另一个列表效果很好,当我加载目标列表时,我发送的项目总是位于最上面。
解决方案
如果你看一下我的代码,我实际上做的是给出了错误的插入地址。错误出现在两个地方。
错误 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" )
}
现在我将我的添加函数指向一个查看目标列表而不是源列表的更新方法:
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")
}
但是当我写这篇文章时,我意识到我遗漏了一个函数来在我执行删除后更新旧列表的排序顺序。这是我可能需要解决的问题!
我在不同的视图中有两个 table,每个 table 的列表在 CoreData 中都有一个单独的实体。用户可以点击任何单元格内的按钮将其移动到另一个列表。这行得通,只需轻按一下即可移动项目,所有内容都会保存并在应用程序关闭后保留。
问题
目前代码应该对目标列表中的项目进行计数,然后将要移动的项目追加到其新列表的末尾。这不会发生。相反,该项目是随机插入的(不是在末尾或开头)。但是,一旦插入,任何进一步移动的项目都将直接位于其下方。我尝试用 1 替换计数函数,因为我真的希望移动的项目无论如何都显示在顶部,但这没有帮助。
代码
首先,这是每次主视图出现时运行加载主列表的 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" )
}
}
关于如何解决这个问题有什么想法吗?理想情况下附加到列表的顶部,但此时将它附加到底部也很好。
我终于弄明白了!
在之前,当我使用该应用程序并查看列表并点击 'move to x list' 获取某个项目时,该项目将被添加到目标列表中的某处中间。
现在,在修复它后,将一个任务从一个列表添加到另一个列表效果很好,当我加载目标列表时,我发送的项目总是位于最上面。
解决方案
如果你看一下我的代码,我实际上做的是给出了错误的插入地址。错误出现在两个地方。
错误 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" )
}
现在我将我的添加函数指向一个查看目标列表而不是源列表的更新方法:
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")
}
但是当我写这篇文章时,我意识到我遗漏了一个函数来在我执行删除后更新旧列表的排序顺序。这是我可能需要解决的问题!