Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Components of XPC service.
import Foundation
let delegate = MyServiceDelegate()
let listener = NSXPCListener.service()
listener.delegate = delegate
listener.resume()
import Foundation
class MyService: NSObject, MyServiceProtocol {
func upperCaseString(_ string: String, withReply reply: @escaping (String) -> Void) {
let response = string.uppercased()
reply(response)
}
}
import Foundation
class MyServiceDelegate: NSObject, NSXPCListenerDelegate {
func listener(_ listener: NSXPCListener, shouldAcceptNewConnection newConnection: NSXPCConnection) -> Bool {
let exportedObject = MyService()
newConnection.exportedInterface = NSXPCInterface(with: MyServiceProtocol.self)
newConnection.exportedObject = exportedObject
newConnection.resume()
return true
}
}
import Foundation
@objc public protocol MyServiceProtocol {
func upperCaseString(_ string: String, withReply reply: @escaping (String) -> Void)
}
import MyService
...
let connection = NSXPCConnection(serviceName: "com.matthewminer.MyService")
connection.remoteObjectInterface = NSXPCInterface(with: MyServiceProtocol.self)
connection.resume()
let service = connection.remoteObjectProxyWithErrorHandler { error in
print("Received error:", error)
} as? MyServiceProtocol
service?.upperCaseString("Hello XPC") { response in
print("Response from XPC service:", response)
}
@Herz3h

This comment has been minimized.

Copy link

@Herz3h Herz3h commented Jul 5, 2018

Thank you very much for this clear and concise example.

@adur1990

This comment has been minimized.

Copy link

@adur1990 adur1990 commented Oct 24, 2018

This is not working with macOS Mojave and Swift 4.2.

The connection to service named com.matthewminer.MyService was invalidated.

Apple's documentation is horrible. I can not figure out how to do this. Any suggestions?

@adur1990

This comment has been minimized.

Copy link

@adur1990 adur1990 commented Oct 25, 2018

So, I figured it our. In Swift 4 you have to pass @escaping to the result parameter of the service:

// MyService.swift

import Foundation

class MyService: NSObject, MyServiceProtocol {
    func upperCaseString(_ string: String, withReply reply: @escaping (String) -> Void) {
        let response = string.uppercased()
        reply(response)
    }
}
// MyServiceProtocol.swift

import Foundation

@objc public protocol MyServiceProtocol {
    func upperCaseString(_ string: String, withReply reply: @escaping (String) -> Void)
}
@mminer

This comment has been minimized.

Copy link
Owner Author

@mminer mminer commented Dec 12, 2018

@adur1990: Thanks for the fix, I updated the Gist.

@madscientistjaidev

This comment has been minimized.

Copy link

@madscientistjaidev madscientistjaidev commented May 29, 2019

@mminer - listener.resume() in main.swift is throwing the following error. Any idea how to fix it?

Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)

@mminer

This comment has been minimized.

Copy link
Owner Author

@mminer mminer commented Jun 26, 2019

@madscientistjaidev: I'm not too sure what might cause that error. I tried the code in the Gist in a fresh project using the Xcode 11 beta + Swift 5 and it worked without a hitch. Sorry I can't be of more help.

@tt-embodied

This comment has been minimized.

Copy link

@tt-embodied tt-embodied commented Jul 30, 2019

Thanks for making your code available.. I reference this every time I create a xpc service and want swift instead. Maybe Xcode 11 will make this obsolete (we can hope).

@mminer

This comment has been minimized.

Copy link
Owner Author

@mminer mminer commented Jul 31, 2019

@tt-embodied: Glad it's helpful!

@antelle

This comment has been minimized.

Copy link

@antelle antelle commented Feb 20, 2020

If anyone like me tried it in a command-line tool and got “The connection to service named ... was invalidated.”, it’s because it doesn’t seem to work in command-line tools at all, the same code in an app will work.

@rsalesas

This comment has been minimized.

Copy link

@rsalesas rsalesas commented Mar 10, 2020

I've tried this in a SwiftUI app and I'm getting the error "The connection to service named ... was invalidated". Any ideas?

UPDATE: My problem was that the XPS Service was not copied to Contents/XPCServices. If you don't properly place the XPC Service within the app bundle, this doesn't work (also why you cannot call the XPC Service from a command line that is expecting it in it's bundle - haven't figure out how to do this yet)

@mminer

This comment has been minimized.

Copy link
Owner Author

@mminer mminer commented Mar 11, 2020

@rsalesas Good to know, that’s an easy mistake to make. Thanks for the extra info.

@ben-z

This comment has been minimized.

Copy link

@ben-z ben-z commented Apr 14, 2020

I also just ran into this error:

Domain=NSCocoaErrorDomain Code=4099 "The connection to service on pid 0 named <service-name> was invalidated."

It turns out I just misspelled the service name when initializing the NSXPCConnection. Hope this saves someone a few hours of debugging lol.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.