How to communicate between Electron and Swift application using Notifications
By
John Phung

There are several ways to communicate between desktop apps which include REST APIās, websockets, system notifications and so onā¦ This post I will focus particularly on a simple way to send data back and forth between a electron app and swift app ā who wouldāve thought this was an actual scenario I encountered at work.
Electron exposes in their APIĀ post and subscription notificationĀ methods that make listening/receiving global events simple. Likewise, Swift hasĀ CFNotificationCenterĀ which allows global OS events to be posted/received. Do not confuse with NotificationCenter as that is limited to the events within the context of the Swift app.
In a nutshell, all we need to do is setup post and subscribe methods in both Electron and Swift apps to establish two-way communication.
Setup Post & Subscribe Methods in Electron
In the main process file in Electron (usually main.js) we want to import the systemPreferences API from Electron.
I would typically place my post and subscribe methods in the app.whenReady() code block. Below is a sample code block of the post and subscribe function setup.
1import {systemPreferences} from "electron"23app.whenReady().then(async () => {45 systemPreferences.subscribeNotification(6 "subscribeEvent",7 (event, userInfo) => {8 console.log(userInfo);9 },10 );1112 // you would probably embed this in a ipcMain event call to hook up to UI13 systemPreferences.postNotification(14 "postEvent",15 {16 // some data17 foo: "bar"18 },19 true,20 );21})
According to the Electron docs, systemPreferences.postNotification takes 3 arguments, event name (string), data to be sent (object) and boolean flag to deliver immediately or not.
systemPreferences.subscribeNotification takes 3 arguments, event name (string), and a callback which exposes the event and the data being received.
Setup Post & Subscribe Methods in Swift
Similar to the Electron setup, we would create a notification listener and specific functions to post notifications to Electron ā you can also post notifications upon receiving them.
You can place the listener or post notification function anywhere, however, for simplicity you can test it by placing it in the AppDelegate. Find below some sample code to subscribe/post global notifications in Swift.
1// AppDelegate.swift23// subscription listener subscribing to "some-event-name" posted by Electron or other app4func observer() {5 CFNotificationCenterAddObserver(CFNotificationCenterGetDistributedCenter(), Unmanaged.passRetained(self).toOpaque(), observerCallback, "some-event-name" as CFString , nil, .deliverImmediately)6}78// the listener callback - do something when you receive "some-event-name" event.9let observerCallback: CFNotificationCallback = { center , observer, name, object, info in10 // perform check on incoming data to see if it exists as a dictionary (object sent from javascript)11 if let data = info as? Dictionary<String, Any> {12 // Check if value present before using it13 guard let method = data["foo"] as? String else { return }14 print(method)15 // we can also post a event back16 postNotification()17 } else {18 print("Could not parse incoming data")19 }20 }2122func postNotification() {23 // create notification event name that other apps will listen to24 let notificationName: CFNotificationName = .init(rawValue: "some-event-name" as CFString)25 // emit notification with data dictionary with key-value as String types26 let data: [String:String] = ["foo":"bar"]27 CFNotificationCenterPostNotification(CFNotificationCenterGetDistributedCenter(), NotificationName, nil, data as CFDictionary, true)28}
Conclusion
I have demonstrated how to implement both post and subscribe methods for notifications in Electron and Swift. Obviously the logic is barebones so it is up to you to extend it for your use case.