XCode+Swift+XPC: как запустить и развернуть цель Swift XPC на MacOS

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Я относительно новичок в MacOS/XCode

Я хочу построить простой XPC Launch Agent в Swift (то есть: в ~/Library/LaunchAgents) но я не смог найти много документации.
Я начал с шаблона XCode XPC, но я не знаю, была ли это хорошая идея для моего быстрого проекта.
Я заметил, что я должен был ~/Library/LaunchAgents/com.demo.myservice.plist

Версии:
- MaOS: 10.13.2
- Xcode: 9,2

Инструкция по созданию проекта XCode XPC:

  1. Файл> Новый проект
  2. Я выбрал шаблон MacOS: XPC
  3. Я создаю пакет 'com.demo.myservice'
  4. Это создает мне проект Objective-C. Поэтому я удаляю все файлы (т.е. myserviceProtocol.h, myservice.h, myservice.m, main.m а также Info.plist
  5. Создайте файлы:

myserviceProtocol.swift

import Foundation

@objc(myserviceProtocol) protocol myserviceProtocol {
    func ping()
}

myservice.swift

import Foundation

class myservice : NSObject, myserviceProtocol {
    func ping() {
        print("ping")
    }
}

main.swift

import Foundation

class ServiceDelegate : NSObject, NSXPCListenerDelegate {
    func listener(_ listener: NSXPCListener, shouldAcceptNewConnection newConnection: NSXPCConnection) -> Bool {
        newConnection.exportedInterface = NSXPCInterface(with:myserviceProtocol.self)
        let exportedObject = myservice()
        newConnection.exportedObject = exportedObject
        newConnection.resume()
        return true
    }
}

// Create the listener and resume it:
//
let delegate = ServiceDelegate()
let listener = NSXPCListener.service()
listener.delegate = delegate;
listener.resume()

Info.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <dict>
        <key>KeepAlive</key>
        <true/>
        <key>Label</key>
        <string>com.demo.myservice</string>
        <key>ProgramArguments</key>
        <array>
            <string>myservice</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
    </dict>
</plist>
  1. Я строю это: введите описание изображения здесь

  2. Я скопировал Info.plist в ~/Library/LaunchAgents/: cp ~/Documents/myservice/myservice/Info.plist ~/Library/LaunchAgents/com.demo.myservice.plist
    Я получаю свой идентификатор пользователя с id -u

И затем я пытаюсь выполнить его из командной строки (поскольку он, похоже, ничего не делает из Xcode):

sudo launchctl debug user/501/com.demo.myservice /Users/olivier/Library/Developer/Xcode/DerivedData/myservice-hbwefcgibyqbajguvblgcmxsnrmd/Build/Products/Debug/myservice.xpc
Configuration failed: 113: Could not find specified service
Could not find service "com.demo.myservice" in domain for uid: 501

Я не совсем уверен в том, что я делаю. Был ли я права использовать XPC Шаблон для создания моей быстрой XPC.

1 ответ

Если вы хотите, чтобы ваш агент предоставлял службу XPC, вам необходимо предоставить ее как службу Mach.

Вы инициализируете свой Listener для службы XPC (обратите внимание на заглавную букву S), служба XPC - это пакет, который является частью пакета вашего приложения, расположенного внутри Contents/XPCServices/ каталог.

Таким образом, вам необходимо:

1.) Создайте агента, который предоставляет службу XPC через службу mach. Ваш слушатель будет выглядеть так:

let listener = NSXPCListener(machServiceName: "com.rderik.exampleXPC" )

2.) Чтобы использовать службу вашего агента, вам необходимо установить соединение с этой службой.

let connection = NSXPCConnection(machServiceName: "com.rderik.exampleXPC")

Надеюсь, это поможет.

Если вы хотите узнать больше, я написал руководство о том, как это сделать здесь:

https://rderik.com/blog/creating-a-launch-agent-that-provides-an-xpc-service-on-macos/

Я не уверен, какова ваша цель. Если вам нужен демон, которым управляет launchd, вам не нужен XPC. Просто создайте демон (возможно, с помощью шаблона проекта Command Line Tool) и создайте файл конфигурации launchd plist (см. man launchd.plist).

XPC предназначен для связи с хост-приложением. Двоичный файл службы должен быть встроен в ваш пакет приложений, и launchd запустит его, когда ваше приложение попытается подключиться. Вам не нужно изменять ~/Library/LaunchAgents для этого.

Ваше приложение должно настроить NSXPCConnection для подключения к XPCListener, который вы создали.

Что-то вроде:

let connection = NSXPCConnection(serviceName: "com.demo.myservice")
let interface = NSXPCInterface(with: myserviceProtocol.self)
connection.remoteObjectInterface = interface
connection.resume()
let proxy = connection.remoteObjectProxyWithErrorHandler {(error) in
            os_log("Connection Error: %{public}@", error.localizedDescription)
        } as! myserviceProtocol

// message proxy here to communicate with service

Оба сценария описаны более подробно в Руководстве по программированию демонов и служб.

Другие вопросы по тегам