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
}
}