Notification on NSUserDefaults Change When App Is In Background

I have two applications that share an app group

@"group.edu.tds.poc.shared"

Using NSUserDefaults of this app group, I am able to exchange data between the reader app and the writer app.

The Writer App writes data to the NSUserDefault

NSUserDefaults *sharedDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.edu.tds.poc.shared"]; [share
dDefaults setObject:stringToStore forKey:key]; 
[sharedDefaults synchronize];

The Reader App reads the data from the NSUserDefault

NSUserDefaults *sharedDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.edu.tds.poc.shared"]; 
return [sharedDefaults stringForKey:@"key"];


I now want the reader app to be notified as soon as the writer app modifies the value for the key. I.e. Can I notify the reader app when the writer app is running in the foreground (Reader app is either running in the background or is not running).

I have implemented the marked solution but with no luck:

Call back only when the Reader App is in foreground state. (Wrote to the Shared Defaults using Reader app)

Any idea if this can be achieved?

Post not yet marked as solved Up vote post of TDS_SAP Down vote post of TDS_SAP
2.5k views

Replies

I now want the reader app to be notified as soon as the writer app modifies the value for the key.

What platform are you working on?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Hi eskimo,


I want to extend this functionality on iOS. (Above iOS 9)

I want to extend this functionality on iOS.

This isn’t possible in the general case on iOS. In most cases the ‘receiving’ app will be suspended, and thus it won’t receive the notification until it gets resumed. Moreover, there’s no general way to force another app to resume in the background.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

I have the same question, but on macOS, does that change the answer? At the moment I’m sending a distributed notification that basically just says “hey, check the shared user defaults, they may have changed”, but maybe there’s a cleaner way.

If your process is running then you can learn about changes to user defaults via KVO. And on macOS it’s easy to keep code running.

Having said that, I’m not a huge fan of KVO and, honestly, your current approach sounds just fine.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I'm trying to use Combine on macOS to get notified of change to app group UserDefaults when made from another process. I've had no end of trouble doing this. There are half a dozen guides online for how to do this in Swift, and I got it working within a single process (with the caveat that the change dictionary always has nil values).

But making a change from another process (e.g. with defaults write) does not result in my KVO or Combine sub getting called (both do get the initial value).

Now, I'm calling .observe() and .publisher(for:) on my UserDefaults object. Apple’s example for block-based KVO calls observe() on self. where self is an NSObject observer subclass, and it observes a key path through its reference to the object with the changing property. Does that matter?

I decided to try DistributedNotificationCenter. It also does not fire when another process sends a notification.

  • I decided to try DistributedNotificationCenter. It doesn't fire at all without deliverImmediately: true, and then I get TWO notifications for each one that I send.

  • I decided to try DistributedNotificationCenter. It doesn't fire at all without deliverImmediately: true, and then I get TWO notifications for each one that I send.

  • Oh, no, my onAppear() was being called twice, and so I was registering twice.

Add a Comment