NSUserDefaultsDidChangeNotification和Today Extensions [英] NSUserDefaultsDidChangeNotification and Today Extensions

查看:114
本文介绍了NSUserDefaultsDidChangeNotification和Today Extensions的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用今日扩展程序开发iPhone应用程序。该应用程序有一个模型模块,可以加载/保存到 NSUserDefaults 。由于我希望主要应用和扩展程序都可以使用此信息,因此我使用应用程序组:

I am developing an iPhone app with a Today Extension. The app has a Model module that loads from/saves toNSUserDefaults. Since I want this information to be available to both the main app and the extension, I use an app group:

let storage = NSUserDefaults(suiteName: "group.etc.etc.etc...")

应用程序和扩展程序可以毫无问题地访问信息。

Both the app and the extension can access the information without any problem.

主应用程序偶尔会创建一个本地通知呈现给用户。该通知有两个与之关联的操作( UIUserNotificationAction )。其中一个操作触发了一些代码在主应用程序的后台运行。该代码更改 NSUserDefaults 信息并触发同步。我的代码是这样的:

The main app occasionally might create a local notification to present to the user. That notification has two actions associated with it (UIUserNotificationAction). One of those actions triggers some code run on the background on the main app. That code changes the NSUserDefaults information and triggers a synchronization. My code is something like this:

func application(application: UIApplication, handleActionWithIdentifier id: String?, forLocalNotification not: UILocalNotification, completionHandler: () -> ()) {
    // Interact with model here
    // New information gets saved to NSUserDefaults
    userDefaultsStorage.synchronize()
    completionHandler()
}

现在,在今日外线。我自然会观察对 NSUserDefaults 上的信息所做的任何更改,以便我可以在窗口小部件上重新加载界面:

Now, on the Today Ext. I naturally observe any changes made to the information on NSUserDefaults so that I can reload the interface on the widget:

override func viewDidLoad() {
    super.viewDidLoad()

    // ...

    NSNotificationCenter.defaultCenter().addObserverForName(NSUserDefaultsDidChangeNotification, object: nil, queue: NSOperationQueue.mainQueue()) { _ in
        self.reload()
    }
}

现在,这是我的问题:


  1. 主应用程序安排UILocalNotification。我打开今天的视图并查看我今天的小部件。

  1. The main app schedules a UILocalNotification. I open the today view and look at my today widget.

当通知触发时,屏幕顶部会出现一个横幅。

When the notification fires, a banner appears on the top of the screen.

我在那个横幅上向下滑动以显示这两个动作,然后我选择我之前提到的那个(今天的小部件仍然在线和屏幕上)。

I slide down on that banner to reveal the two actions and I select the one that I mentioned earlier (the today widget is still live and on screen).

我知道该操作在后台运行正常,并且正在对<$ c上的信息进行更改$ c> NSUserDefaults 。

I know for a fact that the action runs correctly in the background, and that the changes are being made to the information on NSUserDefaults.

然而,即使今天的小部件一直处于活动状态并且一直在屏幕上显示,不会触发重载操作。经过进一步调查,我可以确认 NSUserDefaultsDidChangeNotification 而不是被解雇(我放置了一个断点并且它没有触发,并做了一些其他检查()

However, even though the today widget has been active and on screen all this time, no reload action is triggered. After further investigation, I can confirm that the NSUserDefaultsDidChangeNotification is not being fired (I placed a breakpoint and it did not trigger, and did some other checks as well).

我知道通知操作正在进行更改,因为如果我强制重新加载窗口小部件(通过关闭并打开今天的视图)窗口小部件正确更新。

I know the changes are being made by the notification action because if I force a reload of the widget (by closing and opening the today view) the widget updates correctly.

我在网上看过各种教程,他们说的第一件事是听取这个通知并更新小部件,以便小部件与<同步 code> NSUserDefaults的。但问题是AFAICT这个通知绝对没用!怎么来?

I have seen various tutorials online where the first thing they say is to listen to this notification and update the widget so that "the widget is in sync with NSUserDefaults". But the thing is that AFAICT this notification is absolutely useless! How come??

注1:当我从中的更改NSUserDefaults的信息时今天的小部件通知正确触发。

Note 1: When I change the information on NSUserDefaults from within the today widget the notification fires correctly.

注意2:调试今天的小部件是绝对可怕的,顺便说一句。在对断点和崩溃做出反应之前,总是需要告诉Xcode按名称附加到进程...。 iOS不断为小部件创建一个新的流程,所以我不得不经常告诉Xcode再次附加。

Note 2: Debugging a today widget is absolutely horrible, btw. It is always necessary to tell Xcode to "Attach to process by name..." before it can react to breakpoints and crashes. And iOS is constantly creating a new process for the widget so I have to constantly tell Xcode to attach again.

推荐答案

来自 doc


Cocoa包括两种类型的通知中心:
NSNotificationCenter类管理单个
流程中的通知。 NSDistributedNotificationCenter类在一台计算机上管理多个进程的
通知。

Cocoa includes two types of notification centers: The NSNotificationCenter class manages notifications within a single process. The NSDistributedNotificationCenter class manages notifications across multiple processes on a single computer.

显然,包含应用程序和今天的扩展程序是不同的进程,因为当您调试今天的扩展时,您想要附加包含应用程序进程,但NSNotificationCenter仅在单个进程中工作。

Apparently the containing app and today extension are different processes, since when you debug today extension you want to attach containing app process, but NSNotificationCenter only work within a single process.

为了在包含应用程序和扩展程序之间进行通信,可以使用
达尔文通知中心 CFNotificationCenter ,其工作方式类似于 NSDistributedNotificationCenter ,这是仅适用于osx。

In order to communicate between containing app and extensions, you can use Darwin Notify Center CFNotificationCenterthat works like NSDistributedNotificationCenter, which is only available for osx.

这个想法是使用他们共享的组文件夹中的文件。在包含应用程序时,您将要发送的数据写入文件,然后发布CFNotification,这将由今天的扩展程序接收。

The idea is use a file inside the group folder that they share. in containing app, you write the data you want to send into the file, then post a CFNotification, which will be received by today extension.

在今天的扩展中,使用 CFNotificationCenterAddObserver 观察CFNotification,收到后,将调用回调,其中由于回调是一个C样式函数并且userInfo无法在CFNotification中传递,因此必须发布NSNotification,在收到此NSNotification对象后,它开始从文件中读取数据,该文件用于更新今天的扩展视图通知中心。

In today extension, use CFNotificationCenterAddObserver to observer the CFNotification, upon receiving it, callback will be called, in which a NSNotification has to be posted due to callback is a C style function and "userInfo" cannot be passed in the CFNotification, after receiving this NSNotification object, it starts to read data from the file, which is used to update the today extension view in Notification center.

您可以使用此 github代码来实施强制加载今天的扩展视图。它对我有用。

这是一篇很棒的帖子。 http://www.atomicbird.com/blog/sharing-with-app-extensions

You can use this github code to implement force loading the today extension view. It works for me.
Here is a great post on this. http://www.atomicbird.com/blog/sharing-with-app-extensions

另一种选择是使用setHasContent函数。在计划本地标识符时,将content设置为false以隐藏视图,在 handleActionWithIdentifier 中将其设置为true以显示视图。这样,当您停留在通知中心时,您将暂时看不到该视图,但是当您看到它时,它将是更新的数据。

Another option is to use setHasContent function. When you schedule a local identifier, set has content to false to hide the view, in handleActionWithIdentifier set it to true to show the view. This way, when you stay in notification center, you will not see the view for a moment, but when you see it, it will be the updated data.

let widgetController = NCWidgetController.widgetController()
widgetController.setHasContent(false, forWidgetWithBundleIdentifier: "YourTodayWidgetBundleIdentifier") 

但我认为整个问题是一个罕见的情况,不需要修复,因为您可以获取更新的数据重新加载通知中心或切换到通知选项卡并切换回今天tab。

But I think the whole problem is a rare case, which doesn't need to be fixed since you can get the updated data reloading the notification center or switch to notification tab and switch back to today tab.

这篇关于NSUserDefaultsDidChangeNotification和Today Extensions的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆