There is one xpc server and two xpc clients (clientA and clientB). When clientB sends a message to the xpc server, xpc server fills a value for dummyString in it's memory and I want clientA to know that dummyString got updated and also the new value for this dummyString. The updation of dummyString is not something that happens often.
Two options we tried:
Have a timer for 5 seconds in clientA and keep polling and request for the value of this dummyString.
Setup a darwin notification in server that gets posted whenever dummyString is being updated. clientA receives requests for dummyString value only when it observes a notification being posted.
Which of these two approaches causes the least delay for clientA to know the updated value of dummyString?
Darwin Notify
RSS for tagSend and receive Darwin notifications using Darwin Notify.
Posts under Darwin Notify tag
5 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
I have 2 XPC clients and an XPC server. One of the XPC clients is a binary-helper that serves as a native messaging host for the browserExtension. The other XPC client sends a specific event to the XPC server, which then triggers a Darwin notification. The binary-helper observes this Darwin notification and sends a response to the browserExtension.
Currently, we're considering two options to communicate the response from binary-helper to browserExtension:
Polling: Every 5 seconds, the browserExtension checks for a response.
Darwin Notifications: The binary-helper sends a message to the browserExtension as soon as it observes the Darwin notification.
I'm wondering if Darwin notifications are fast enough to reliably deliver this response to the browserExtension in real time, or if polling would be a more reliable approach. Any insights or experiences with using Darwin notifications in a similar scenario would be greatly appreciated.
Hi,
I'm facing an issue with Darwin notifications between two applications that share the same App Group.
Issue Description:
When the app is in the foreground (active state), the notifications are received and handled correctly.
However, when the app is in the background, notifications are not received.
What I've Tried:
Verified the App Group is correctly configured and accessible between the two applications.
Confirmed Darwin notifications are triggered and received successfully in the foreground.
Checked notification permissions and ensured all required capabilities are enabled.
Setup Details:
iOS version: iOS 11
Xcode version: 16.0
Notifications: Darwin notifications sent between apps using App Groups.
**Code Snippet : **
func startListening(name: String, callback: @escaping () -> Void) {
CFNotificationCenterAddObserver(notificationCenter,
Unmanaged.passUnretained(self).toOpaque(),
NotificationManager.notificationCallback,
name as CFString,
nil,
.deliverImmediately)
}
func sendNotification(name: String) {
CFNotificationCenterPostNotification(notificationCenter, CFNotificationName(name as CFString), nil, nil, true)
}
private static let notificationCallback: CFNotificationCallback = { center, observer, name, _, _ in
guard let observer = observer else { return }
let manager = Unmanaged.fromOpaque(observer).takeUnretainedValue()
if let name = name?.rawValue as String {
// Code added
}
}
Is there any additional configuration or specific behavior of Darwin notifications in the background that could be causing this issue?
I would greatly appreciate any insights, guidance, or references to relevant documentation.
Thank you!
I would really like to know if it is possible to get a state for the ringer on iOS. In my application I want to repeat the logic of audio rules from Instagram during watching a video.
The video plays with sound. When the ringer switches to mute status the video's audio should be muted too. When you press the volume up or down button the audio should be unmuted.
I found how to catch volume up/down buttons with AVAudioSession.sharedInstance().observe(\.outputVolume) but I couldn't find anything that could help me with the ringer state. AVAudioSession.Category can't achieve this effect.
Also there is a possibility to check ringer state with Darwin notify lib like
var token = NOTIFY_TOKEN_INVALID
notify_register_dispatch(
"com.apple.springboard.ringerstate",
&token,
.main
) { token in
var state: UInt64 = 0
notify_get_state(token, &state)
print("Changed to", state == 1 ? "ON" : "OFF")
}
but I'm not sure that this won't lead to the application being rejected. I don't know is it a private API usage or not.
I will be glad to any advice and suggestions. Thanks
As per our code, we have the apps to be shielded whenever the threshold is reached. According to this use-case, our code in DeviceActivityExtension looks something like:
override func eventDidReachThreshold(_ event: DeviceActivityEvent.Name, activity: DeviceActivityName) {
super.eventDidReachThreshold(event, activity: activity)
defaults?.setValue(event.rawValue, forKey: "appLimitEventName")
defaults?.setValue(true, forKey: "appLimitReached")
defaults?.synchronize()
// using darwinNotificationCenter to trigger callback in the application
let darwinNotificationCenter = DarwinNotificationsManager.sharedInstance()
darwinNotificationCenter.postNotification(withName: "nextAppLimitInitiated")
// using Notifications to debug since print doesn't work
scheduleNotification(with: "interval threshold reached")
}
And in our application, we have the shielding logic in place,
init() {
let darwinNotificationCenter = DarwinNotificationsManager.sharedInstance()
darwinNotificationCenter.register(forNotificationName: "nextAppLimitInitiated"){
print("callback received")
let appLimitReached = self.defaults?.bool(forKey: "appLimitReached")
let appLimitEventName = self.defaults?.string(forKey: "appLimitEventName")
if appLimitReached ?? false, appLimitEventName != "" {
// this sends the notification when callback is received
self.scheduleNotification(with: "init start")
self.defaults?.setValue(false, forKey: "appLimitReached")
guard var dataArray = self.defaults?.array(forKey: "appLimitdataArray"), !dataArray.isEmpty else {
return
}
let appLimitData = dataArray.first as! NSDictionary
let appLimitKey = appLimitData["appLimitId"] as! String
let data = self.getSchedule(key: appLimitEventName ?? "")
if let appTokens = data?.applicationTokens {
for token in appTokens {
if !self.applicationTokens.contains(appTokens) {
self.applicationTokens.insert(token)
}
}
}
self.store.shield.applications = self.applicationTokens
self.store.shield.applicationCategories = ShieldSettings.ActivityCategoryPolicy.specific(self.categoryTokens, except: Set())
dataArray.removeFirst()
//dataArray.append(appLimitData)
self.defaults?.set(dataArray, forKey: "appLimitdataArray")
self.initiateMonitoring(initiateAgain: true)
self.scheduleNotification(with: "init end")
}
}
}
This works as expected for multiple App Limits but only when the device is connected to the Xcode. If we disconnect the device from Xcode/ stop application from Xcode/ try in release mode, the callback is not received from extension to the app/init block.
When the device is connected to Xcode, if the apps hit the threshold, they are shielded automatically. But if the device is disconnected/ app is in release mode, the apps are not shielded automatically even after the threshold is reached. It is shielded later only after opening our app once.
Please let me know if I'm doing anything wrong in receiving callback or in my shielding logic. If I need to place the shielding logic in the extension, please tell me how I can handle multiple appTokens.