Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 今日扩展:与容器应用程序同步数据 上下文_Ios_Swift_Ios App Extension_Ios8 Today Widget_Today Extension - Fatal编程技术网

Ios 今日扩展:与容器应用程序同步数据 上下文

Ios 今日扩展:与容器应用程序同步数据 上下文,ios,swift,ios-app-extension,ios8-today-widget,today-extension,Ios,Swift,Ios App Extension,Ios8 Today Widget,Today Extension,我今天一直在玩扩展 该应用程序非常简单: 在包含的应用程序中,您有一个待办事项列表,您可以将其标记为已完成 在Today小部件中,您可以看到相同的列表,但是您可以使用分段控件在已完成项和未完成项之间切换 我的目标如下:每当容器应用程序或小部件中发生数据更改时,我希望两者都反映更改: 如果我在容器应用程序中将一个项目标记为已完成,然后拉下通知中心,小部件应该会更新 当我在小部件中执行相同操作,然后返回到应用程序时,应用程序的状态应该更新 实施 我理解,容器应用程序和扩展在各自的进程中运行,

我今天一直在玩扩展

该应用程序非常简单:

  • 在包含的应用程序中,您有一个待办事项列表,您可以将其标记为已完成
  • 在Today小部件中,您可以看到相同的列表,但是您可以使用分段控件在已完成项和未完成项之间切换
我的目标如下:每当容器应用程序或小部件中发生数据更改时,我希望两者都反映更改:

  • 如果我在容器应用程序中将一个项目标记为已完成,然后拉下通知中心,小部件应该会更新
  • 当我在小部件中执行相同操作,然后返回到应用程序时,应用程序的状态应该更新
实施 我理解,容器应用程序和扩展在各自的进程中运行,这意味着两个约束:

  • nsUserDefaultsIDChangeNotification
    无效
  • 在内存中管理模型实例是无用的
我还知道,为了访问共享容器,两个目标必须选择使用相同组Id下的应用程序组权限

数据访问由嵌入式框架管理。与其将属性保留在内存中,不如直接转到
NSUserDefaults
,以获取适当的值:

public struct ShoppingItemStore: ShoppingStoreType {

    private let defaultItems = [
        ShoppingItem(name: "Coffee"),
        ShoppingItem(name: "Banana"),
    ]

    private let defaults = NSUserDefaults(suiteName: appGroupId)

    public init() {}

    public func items() -> [ShoppingItem] {
        if let loaded = loadItems() {
            return loaded
        } else {
            return defaultItems
        }
    }

    public func toggleItem(item: ShoppingItem) {

        let initial = items()

        let updated = initial.map { original -> ShoppingItem in
            return original == item ?
                ShoppingItem(name: original.name, status: !original.status) : original
        }

        saveItems(updated)
    }

    private func saveItems(items: [ShoppingItem]) {

        let boxedItems = items.map { item -> [String : Bool] in
            return [item.name : item.status]
        }

        defaults?.setValue(boxedItems, forKey: savedDataKey)
        defaults?.synchronize()
    }

    private func loadItems() -> [ShoppingItem]? {

        if let loaded = defaults?.valueForKey(savedDataKey) as? [[String : Bool]] {

            let unboxed = loaded.map { dict -> ShoppingItem in

                return ShoppingItem(name: dict.keys.first!, status: dict.values.first!)
            }

            return unboxed
        }

        return nil
    }
}
问题 以下是有效的方法:

  • 当我修改主应用程序中的列表,然后停止模拟器,然后从Xcode启动今日目标时,它会反映正确的状态。这是事实,反之亦然
这将验证我的应用程序组设置是否正确

然而,当我在主应用程序中更改某些内容,然后拉下通知中心时,它完全不同步。这就是我不明白的部分

我的视图直接从共享容器获取数据。每当发生更改时,我都会立即更新共享容器中的数据

我错过了什么?如何正确地同步这两个?我的数据访问类没有管理任何状态,但我不理解它为什么不能正常工作

附加信息
  • 我知道。不幸的是,这不是我的选择,因为我需要在不包含任何第三方解决方案的情况下实现适当的功能

  • 这篇文章涵盖了这个主题,我可能需要使用
    NSFilePresenter
    ,尽管它看起来很麻烦,而且我还不完全了解其机制。我真的希望有一个比这个更简单的解决办法


    • 我在这里学到了两件事:

      首先,总是仔细检查你的权利,我的权利不知怎么搞砸了,这就是为什么共享容器的行为如此尴尬的原因

      第二: 虽然不会调用
      视图(:)
      ,但当您关闭通知中心时,仍然可以从您的应用程序代理触发更新:

      func applicationDidBecomeActive(application: UIApplication) {
          NSNotificationCenter.defaultCenter().postNotificationName(updateDataNotification, object: nil)
      }
      
      然后在视图控制器中:

      override func viewWillAppear(animated: Bool) {
          super.viewWillAppear(animated)
      
          NSNotificationCenter.defaultCenter().addObserverForName(updateDataNotification, object: nil, queue: NSOperationQueue.mainQueue()) { (_) -> Void in
              self.tableView.reloadData()
          }
      }
      
      override func viewDidDisappear(animated: Bool) {
          super.viewDidDisappear(animated)
          NSNotificationCenter.defaultCenter().removeObserver(self)
      }
      
      更新Today小部件很简单:每次关闭通知中心时,都会调用
      视图(:)
      ,因此您可以在那里查询新数据

      我将很快更新GitHub上的示例项目