はじめに
DistributedNotificationCenter
(https://developer.apple.com/documentation/foundation/distributednotificationcenter)
はmacOSのアプリでプロセス間通信を行う際にとても便利だが、userInfoにはPure swiftな型 (StringとかIntとか) しか含めることができないらしい。
やったこと
Notificationの送信側と受信側2つのアプリを用意し、↓ のように実装する。
送信側のSandboxがonになっているとuserInfoを含めることができないので、Sandboxはoffにしておく。
import Cocoa
class ViewController: NSViewController {
override func viewDidLoad() {
super.viewDidLoad()
let dnc = DistributedNotificationCenter.default()
// userInfoにstringを含める
dnc.postNotificationName(NSNotification.Name("StringUserInfo"), object: nil, userInfo: ["value": "hogehoge"], deliverImmediately: true)
// userInfoにURLを含める
dnc.postNotificationName(NSNotification.Name("URLUserInfo"), object: nil, userInfo: ["value": URL(string: "https://www.google.com")!], deliverImmediately: true)
}
}
import Cocoa
class ViewController: NSViewController {
private var observers = [NSObjectProtocol]()
override func viewDidLoad() {
super.viewDidLoad()
let dnc = DistributedNotificationCenter.default()
let o1 = dnc.addObserver(forName: NSNotification.Name("StringUserInfo"), object: nil, queue: OperationQueue.main) { n in
print("Can receive")
print(n)
}
observers.append(o1)
let o2 = dnc.addObserver(forName: NSNotification.Name("URLUserInfo"), object: nil, queue: OperationQueue.main) { n in
print("Cannot receive")
print(n)
}
observers.append(o2)
}
}
上記の実装で実行してみると、 StringUserInfo
の方は正しく受信できるが URLUserInfo
の方は受信できない。
これでちょっとハマった。
考えたこと
冷静になってみると、受け取った側でどんな型かわからん状況が容易に想像できるので、安全のために絶対に型がわかるuserInfoしか送れないようになっているんだと思う。
Objective-Cでどうなるかは試していない。
終わりに
Primitiveな型しか扱えなかったりuserInfoを渡すにはSandboxがoffになっていないといけなかったり何かと制約は多いが、プロセス間通信したい場合にはとても便利なので積極的に使っていこう。
なお、今回の挙動はこちらで試せる。
https://github.com/yamazaki-sensei/distributed_notification_sample.git