WatchKit 和 CoreData 的奇怪问题

Posted

技术标签:

【中文标题】WatchKit 和 CoreData 的奇怪问题【英文标题】:Weird issue with WatchKit and CoreData 【发布时间】:2015-04-20 18:30:19 【问题描述】:

我正在使用 WatchKit 和 CoreData,我编写的演示应用程序正在运行,但有时会产生意想不到的结果。基本上,它是一个待办事项应用程序。您在 iPhone 上输入 toDo 项目,它使用 CoreData 将它们存储在一个名为 ToDoItem 的实体中,该实体具有 2 个属性:名称(字符串)和已完成(布尔值)。在 iPhone 上输入的项目名称在 CoreData 实体中分配为 item.completed = false

在 Apple Watch 上,它在 iPhone 上查询 CoreData,并在 WatchKit 表视图中列出未完成项目的名称 (item.completed == 0)。当手表上的一个项目被选中时,字体变为红色,该行从表中删除,并将 CoreData 中的完成值更改为 true (item.completed = true)。下次启动 Watch 应用时,表格中不再列出已完成的项目。

这在大多数情况下都可以正常工作,但有时当在手表上选择一个项目时,它不会将 CoreData 更新为 item.completed = true 的项目。一旦发生这种情况,它就不再在选择时更新 CoreData 中的项目。没有给出错误。如果我重置模拟器,它会再次开始工作,但一段时间后会做同样的事情。

我的代码如下:

class InterfaceController: WKInterfaceController 


@IBOutlet var table: WKInterfaceTable!

override func awakeWithContext(context: AnyObject?) 
    super.awakeWithContext(context)

    // Configure interface objects here.

    var context = CoreDataStack.sharedInstance.managedObjectContext!

    let request = NSFetchRequest(entityName: "ToDoItem") //CoreData entity ToDoItem contains two attributes - name (string) and completed (boolean)

    let fetchItems: Array = context.executeFetchRequest(request, error: nil) as! [ToDoItem] //fetches the items in the entity

    var counter = 0

    for element in fetchItems

        counter++

        println("The item name is \(element.name) and completed is \(element.completed)") //prints the items to the console


    



    self.table.setNumberOfRows(fetchItems.count, withRowType: "ToDoRow")

    var theCount = 0
    for element in fetchItems 

        if element.completed == 0 

        let row = self.table.rowControllerAtIndex(theCount) as? ToDoTableRowController
        row?.nameLabel.setText(element.name) //populates the table with names of items that are not completed
        theCount++
        

    






override func table(table: WKInterfaceTable, didSelectRowAtIndex rowIndex: Int) 
    //self.pushControllerWithName("ToDoDetail", context: nil)

    let row = table.rowControllerAtIndex(rowIndex) as! ToDoTableRowController
    row.nameLabel.setTextColor(UIColor.redColor()) //change the color of font to red when row is selected


    var myIndex = NSIndexSet(index: rowIndex)

    self.table.removeRowsAtIndexes(myIndex) //removes selected row from table


    var context = CoreDataStack.sharedInstance.managedObjectContext!

    let request = NSFetchRequest(entityName: "ToDoItem")

    let items = context.executeFetchRequest(request, error: nil) as! [ToDoItem]


    let item = items[rowIndex]

    item.setValue(true, forKey: "completed") //changes the selected item to completed and saves it in coredata

    //item.completed = true 

    var error: NSError?

    if !context.save(&error) 

        println("Cannot save due to \(error) \(error?.localizedDescription)")
    




【问题讨论】:

你检查过'save'返回的错误吗? 我在关键点 - item.setvalue 和 context.save 处创建了断点,但一切正常。我不知道这是否是 watchKit 模拟器中的错误,并且无法使用 Apple Watch 设备进行测试,因为我还没有。我看到一篇文章可能会有所帮助。如果我找到这个问题的答案,我会更新这篇文章。 【参考方案1】:

您如何协调主机应用和手表扩展程序之间的数据?我在应用程序组容器中使用核心数据存储,我发现手表、今日小部件和主机应用程序在保存强制合并发生之前没有获得对托管对象的更新。 (托管对象上下文不会注意到存储中的对象已更改。)因此可能是手表的上下文具有已完成的项目,但主机应用程序的上下文中仍有未完成的项目。

我的解决方法是使用MMWormhole,这样所有三个二进制文件在接触NSManagedObject 子类时都可以相互更新。我在消息中传递了object ID,当二进制文件收到消息时调用 context.refreshObject(managedObject, mergeChanges: true) 让所有人重新同步。

【讨论】:

以上是关于WatchKit 和 CoreData 的奇怪问题的主要内容,如果未能解决你的问题,请参考以下文章

WatchKit 和 MagicalRecord - 这可能吗?

WatchKit 核心数据同步

WatchKit:视频时长

如何在 WatchKit 扩展目标中获取核心数据持久存储路径

WatchKit 2 并发症文本仅在预览中显示

删除对象时CoreData的奇怪行为