Macアプリでコマンドラインツールやアプリを内包してサブタスクとして起動している時などに本体アプリと通信を行いたい時がある。
DistributedNotificationCenter を使用すればアプリ間通信が可能になる。
サンプルコードは以下に配置。
https://github.com/atsushijike/DistributedNotifications
- Xcode10.1
- Swift4.2
送信側
NotificationCenter と同じようにpostするのだが、 post(name:,object:) や post(name:,object:,userInfo:) を使うと受信側アプリを前面にしないとobserveされなかったりするので、 postNotificationName(_ name:,object:,userInfo:,deliverImmediately:) を使用する。
userInfo には field.stringValue を"Message"キーで入れている。
@IBAction func post(_ sender: NSButton) {
let userInfo: [AnyHashable : Any]? = field.stringValue.isEmpty ? nil : ["Message" : field.stringValue]
DistributedNotificationCenter.default().postNotificationName(NSNotification.Name("DistributedNotifications.Post"), object: nil, userInfo: userInfo, deliverImmediately: true)
}
但し、Sandbox対応アプリで userInfo を含むとエラーになるので注意
https://developer.apple.com/library/archive/documentation/Security/Conceptual/AppSandboxDesignGuide/DesigningYourSandbox/DesigningYourSandbox.html
With App Sandbox, you cannot include a userInfo dictionary when posting to an NSDistributedNotificationCenter object for messaging other tasks.
受信側
NotificationCenter でobserveするときと同様に addObserver(_ observer:,selector:,name:,object:) する。
func applicationDidFinishLaunching(_ aNotification: Notification) {
DistributedNotificationCenter.default().addObserver(self, selector: #selector(distributedNotificationsPost), name: NSNotification.Name("DistributedNotifications.Post"), object: nil)
}
userInfo に含まれる"Message"を label に表示。
@objc private func distributedNotificationsPost(notification: Notification) {
if let message = notification.userInfo?["Message"] as? String {
label.stringValue = message
}
}
