gpt4 book ai didi

ios - 今天扩展 : syncing data with container app

转载 作者:搜寻专家 更新时间:2023-11-01 07:34:25 25 4
gpt4 key购买 nike

上下文

我一直在使用 this example project 来尝试 Today Extensions | .

该应用程序非常简单:

  • 在包含的应用程序中,您有一个待办事项列表,您可以将其标记为已完成
  • 在“今日”小部件中,您会看到相同的列表,但您可以使用分段控件在已完成和未完成的项目之间切换。

我的目标如下:每当容器应用程序或小部件中发生数据更改时,我希望两者都能反射(reflect)更改:

  • 如果我在容器应用程序中将某个项目标记为已完成,然后拉下通知中心,小部件应该会更新
  • 当我在小部件中执行相同操作,然后返回到应用程序时,应用程序的状态应该会更新

实现

据我所知,容器应用程序和扩展程序在各自的进程中运行,这意味着两个约束:

  • NSUserDefaultsDidChangeNotification 没用。
  • 在内存中管理模型实例是没有用的。

我也知道,为了访问共享容器,两个目标都必须选择加入同一组 ID 下的应用程序组权利。

数据访问由嵌入式框架管理,TodoKit .它不是将属性保存在内存中,而是直接进入 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 启动 Today 目标时,它反射(reflect)了正确的状态。反之亦然。

这证明我的应用组设置正确。

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

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

我错过了什么?我怎样才能正确同步这两个?我的数据访问类不是 managint any 状态,但我不明白为什么它的行为不正确。

附加信息

  • 我知道 MMWormhole .不幸的是,这对我来说不是一个选择,因为我需要在不包括任何第三方解决方案的情况下实现适当的功能。

  • terrific article ,涵盖了主题,我可能需要使用 NSFilePresenter,尽管它看起来很麻烦,而且我还没有完全理解该机制。我真的希望有比这个更简单的解决方案。

最佳答案

好吧,我在这里学到了两件事:

首先,始终仔细检查您的权利,我的权利不知何故搞砸了,这就是共享容器表现如此笨拙的原因。

第二个:虽然 viewWillAppear(_:) 没有被调用,但是当您关闭通知中心时,仍然可以从您的应用程序委托(delegate)中触发更新:

func applicationDidBecomeActive(application: UIApplication) {
NSNotificationCenter.defaultCenter().postNotificationName(updateDataNotification, object: nil)
}

然后在你的 View Controller 中:

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 小部件很简单:每次下拉通知中心时,viewWillAppear(:_) 都会被调用,因此您可以在那里查询新数据。

我会尽快更新 GitHub 上的示例项目。

关于ios - 今天扩展 : syncing data with container app,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30822988/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com