如何更新 Core Data 的用户界面?

Posted

技术标签:

【中文标题】如何更新 Core Data 的用户界面?【英文标题】:How to update user interface on Core Data? 【发布时间】:2016-01-25 02:54:42 【问题描述】:

我还有一个带有 UITableView、Core Data 和 NSFetchedResultsController 的应用程序。我已将数据传递给 DetailViewController。我可以从 DetailViewController 中删除它们!在 Apple 的 ios Notes 应用程序中,您可以看到我想要的功能!当您从 DetailViewController 中删除笔记时(例如),对象已删除,Notes 应用程序会自动显示下一个或上一个笔记!我想创建这样的功能。删除当前对象后如何更新用户界面?这是我的代码!谢谢` 导入 UIKit 导入核心数据

类 DetailViewController: UIViewController

@IBOutlet weak var containerLabel: UILabel!

var retrieveData:NSManagedObject!
var managedObjectContext:NSManagedObjectContext!
var manager:Manager!

override func viewDidLoad() 
    super.viewDidLoad()
// Do any additional setup after loading the view.

    self.containerLabel.userInteractionEnabled = false
    self.containerLabel.textColor = UIColor.redColor()
    self.containerLabel.alpha = 0

    UIView.animateWithDuration(2.5)  () -> Void in
        self.containerLabel.alpha = 1
    


    if let demo = self.retrieveData.valueForKey("titleField") as? String 
     self.containerLabel.text = demo
    



override func didReceiveMemoryWarning() 
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.


@IBAction func backToMain(sender: AnyObject) 
    // Back to the MainTableViewController
    self.dismissViewControllerAnimated(true, completion: nil)

@IBAction func trashButton(sender: AnyObject) 

    self.managedObjectContext.deleteObject(retrieveData)

    do 
    try self.managedObjectContext.save()
     catch 

    
    self.dismissViewControllerAnimated(true, completion: nil)



`

如果我在列表中有 5 个项目,如下所示:

当我从列表中选择第四项时(例如)。 detailVC 会像这样向我显示选定的项目:

我想删除它们。当我删除“四”然后我的containerLabel.text 显示列表中的先前对象时。他们在“四”被删除之后,“三”、“二”和“一”也是如此。删除“一”后,我的containerLabel.text 显示字符串

但我留下了一个名为“五”的对象

我的问题是“五”!我不能删除它。示例:在 iOS Notes 应用程序中,如果您的列表中有五个对象,例如我的演示应用程序。当您从列表中选择第四个对象时(例如 )。并开始删除它们,在“四”被删除后 iOS Notes App 显示“五”。并且“五”(列表中的最后一个对象)被删除,然后 iOS Notes App 显示“三”、“二”和“一”。也许问题线在这里:

if index != 0 self.retrieveData = fetchedObject[index! - 1] else self.retrieveData == fetchedObject[0]

【问题讨论】:

【参考方案1】:

让我们在这里采取简单(但不那么优雅)的路线。您必须将所有获取的对象传递给详细信息 VC,如下所示:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) 

if segue.identifier == "yourSegueIdentifier"

    if let destinationVC = segue.destinationViewController as? DetailViewController

        destinationVC.managedObjectContext = yourContext
        destinationVC.retrieveData = yourManagedObject
        destinationVC.arrayOfFetchedObjects = yourFetchedResultsController.fetchedObjects
        //pass over other data...

        
    

然后,在您的 detailVC 中,编写一个方法,当您按下删除按钮时将执行该方法。像这样的:

@IBAction func trashButton(sender: AnyObject) 

//make sure you have an array with YourObjects
guard let fetchedObjects = arrayOfFetchedObjects as? [YourObjectType] else return

//get index of the shown object in the array of fetched objects
let indexOfObject = fetchedObjects.indexOf(retrieveData)

//delete the object from the context
self.managedObjectContext.deleteObject(retrieveData)

do 
    try self.managedObjectContext.save()

    //delete the object from the fetchedObjects array
    fetchedObjects.removeAtIndex(indexOfObject)
 catch 



//get the object that should be shown after the delete
if indexOfObject != 0
    //we want the object that represents the 'older' note
    retrieveData = fetchedObjects[indexOfObject - 1]
    updateUserInterface(true)


else
    //the index was 0, so the deleted object was the oldest. The object that is the oldest after the delete now takes index 0, so just use this index. Also check for an empty array.

    if fetchedObjects.isEmpty 
         updateUserInterface(false)
     
    else
        retrieveData = fetchedObjects[0]
        updateUserInterface(true)
    

    



func updateUserInterface(note: Bool)

switch note

    case true:

        //update the user interface
        if let demo = retrieveData.valueForKey("titleField") as? String 
            self.containerLabel.text = demo
        

    case false:

        self.containerLabel.text = "no more notes"

    

【讨论】:

酷!我会试试...谢谢@Tuslareb 当我在数组上有多个项目时,效果很好!如果我有单品? Xcode 给了我这样的错误! “致命错误:数组索引超出范围”。 那是因为您正在访问空数组上的索引 0。所以你会得到一个超出范围的错误。正如我所说,在尝试获取 fetchedObjects[0] 之前,您需要一些代码来检查空数组。在这种情况下,不要为retrieveData 分配新值。您可以使用以下文字更新用户界面:“列表中没有笔记”或类似内容。 if index == 0 self.containerLabel.text = "No Records Are Available!" self.secondContainerLabel.text = "" self.trash.enabled = false 它有效,但不显示列表中的下一个对象。只显示以前的对象。我已经编辑了我的问题。请检查一下。 您没有检查空数组。您只是在检查索引是否为 0。我编辑了答案。【参考方案2】:

你要么需要传递细节视图控制器

    所有托管对象的列表和列表中起始位置的索引 当前托管对象和获取下一个对象的回调

为了让它有足够的信息来做你想做的事。回调方法是最好的,是一种简单的委托形式,您的主视图控制器是提供额外数据的委托。

【讨论】:

我尝试了很多方法!但它们不再起作用了!我的朋友@Tuslareb 已经说过了!如果我从 detailVC 中删除当前对象,它会显示已删除的对象!不更新!你能通过代码帮助我吗?非常感谢! 你接受了这个答案,这是否意味着你已经运行了? 我不太明白@user5546017 的评论。您是说详细 VC 更新列表而主 VC 没有反映这一点吗?这是一个不同的问题。理想情况下,您应该使用获取的结果控制器 亲爱的@Wain!我是 iOS 开发的新手!我有一个 tableView 并且我已经完全完成了 NSFetchedResultsControllerDelegate 协议方法!我的 masterVC ( MainVC ) 完美运行!没有任何错误!我可以顺利地插入、删除、更新行。我已通过 prepareForSegue 将数据传递给 detailVC。我可以从 detailVC 中删除它们。非常感谢@Tuslareb !我的问题是删除后!因为我的 containerLabel 仍然显示已删除的对象!不更新!你懂了吗?如何实现? 亲爱的朋友@Tuslareb!我不测试它们!因为没看懂。如何得到它们?如何回调以获取下一个对象?我需要你的帮助!谢谢!

以上是关于如何更新 Core Data 的用户界面?的主要内容,如果未能解决你的问题,请参考以下文章

iPhone 和 Core Data:如何在更新之间保留用户输入的数据?

静态应用程序数据和可更新用户数据与 Core Data 之间的关系

如何更新 UI 以显示 Core Data 长时间运行的进程?

带有命令行界面的 Core Data Cocoa 应用程序

Core Data SQLite 存储在更新后变为只读

在应用程序运行时替换 Core Data sqlite 文件,数据不更新