RadioLog
RadioLog

Reputation: 602

NSUserDefaultsDidChangeNotification not sent

While working with data sharing between iOS app and Today Extension, I faced the problem that the NSUserDefaultsDidChangeNotification is never sent from either main app or extension when I change UserDefaults. The thing is that I can read and write data to the UserDefaults successfully for the App Group I created. So the data is actually shared by the app and extension. But the notification of the UserDefaults change is never fired (or detected). Can somebody tell me what can be an issue?

The writing of the data in the UserDefaults

NSUserDefaults defaults = new NSUserDefaults("group.com.name1.name2",NSUserDefaultsType.SuiteName);
defaults.SetString("UPDATE " + DateTime.Now.Minute, "data");
defaults.Synchronize();

The notification handler

NSNotificationCenter.DefaultCenter.AddObserver(
                NSValueTransformer.UserDefaultsDidChangeNotification, (notification) => {
    NSUserDefaults defaults = new NSUserDefaults("group.com.name1.name2",NSUserDefaultsType.SuiteName);
    string str = defaults.StringForKey("data");  
});

Upvotes: 1

Views: 660

Answers (2)

RadioLog
RadioLog

Reputation: 602

So, SushiHangover provided perfectly working piece of code. However, the problem was in the Info.plist file. In order to be able to exchange the notification the Background Mode should be enable for the app with Remote Notification feature. It sounds like a very obvious thing to do, but none of the tutorials for exchanging data between Extension and app with User Defaults that I read mentioned this. Perhaps, it is an obvious thing to do. But I am writing this just in case somebody might have missed this thing too.

Upvotes: -1

SushiHangover
SushiHangover

Reputation: 74174

You can use CFNotificationCenter from your container app to post a cross-process notification to your extension app.

Shared Constants:

const string id = "group.sushihangover";
const string key = "LastUpdateTime";

Container app / Setup an observer on your NSUserDefaults object:

var todayWidgetUserDefaults = new NSUserDefaults(id, NSUserDefaultsType.SuiteName);

NSValueTransformer.Notifications.ObserveUserDefaultsDidChange(todayWidgetUserDefaults,(sender, e) => 
{
     CFNotificationCenter.Darwin.PostNotification(id, todayWidgetUserDefaults, null, true, true);
});

Today Extension App:

var todayWidgetUserDefaults = new NSUserDefaults(id, NSUserDefaultsType.SuiteName);

void ObserverAction(string notificationId, NSDictionary userInfo)
{
    if (notificationId == id)
    {
        Console.WriteLine(todayWidgetUserDefaults.StringForKey(key));
    }
}
var observerToken = CFNotificationCenter.Darwin.AddObserver(id, todayWidgetUserDefaults, ObserverAction, CFNotificationSuspensionBehavior.DeliverImmediately);

Note: App Group entitlements must be setup in both your container app and the Today Extension App.

Upvotes: 2

Related Questions