import Foundation class ProcessCommunicatorSender: NSObject { private var appGroupIdentifier: String private var remotePort: CFMessagePort? init(appGroupIdentifier: String) { self.appGroupIdentifier = appGroupIdentifier super.init() self.remotePort = CFMessagePortCreateRemote(nil, appGroupIdentifier as CFString) } /** Send an event to the app group with a specified id and some data */ func send(id: Int32, data: Data) -> Bool { if let port = self.remotePort { return CFMessagePortSendRequest(port, id, data as CFData, 1, 1, nil, nil) == kCFMessagePortSuccess } return false } } class ProcessCommunicatorReceiver: NSObject { private var appGroupIdentifier: String private var port: CFMessagePort? private var events: [Int32: (Data) -> Data?] init(appGroupIdentifier: String) { self.appGroupIdentifier = appGroupIdentifier self.events = [:] super.init() var context = CFMessagePortContext(version: 0, info: bridgedPtr(self), retain: nil, release: nil, copyDescription: nil) var shouldFreeInfo: DarwinBoolean = false port = CFMessagePortCreateLocal(nil, appGroupIdentifier as CFString, eventHandler(), &context, &shouldFreeInfo) let source = CFMessagePortCreateRunLoopSource(nil, port, 0) CFRunLoopAddSource(CFRunLoopGetCurrent(), source, CFRunLoopMode.commonModes) } @objc func handleEvent(_ msgid: Int32, data: Data) -> Data? { print("Event received with id \(msgid)") if events.contains(where: { $0.key == msgid }) { if let event = events[msgid] { return event(data) } } return nil } /** Registers an event callback for a specific id-event. The event is called if a message with the specified event-id is sent within the app group */ func on(id: Int32, event: @escaping (Data) -> Data?) { self.events[id] = event } }