Servizi XPC su app macOS
Prima di XPC prendevamo Sockets e Mach Messages (Mach Ports).
Il meccanismo XPC offre un’alternativa ai socket (o ai servizi Mach usando MIG) per l’IPC. Potremmo avere, per esempio, un processo che agisce come “server” in attesa che i client accedano alle sue API e forniscano qualche servizio.
Servizi XPC sulle applicazioni
Quando si parla di Servizi XPC (S maiuscola), ci si riferisce al bundle chiamato Servizio XPC. I bundle nell’ecosistema Apple si riferiscono a entità rappresentate da una specifica struttura di directory. I bundle più comuni che si incontrano sono i bundle delle applicazioni. Se clicchi con il tasto destro del mouse su qualsiasi applicazione (per esempio Chess.app) e selezioni Show content, quello che troverai è una struttura di directory. Tornando a XPC, le applicazioni possono avere più bundle di servizi XPC. Li troverai all’interno della directory Contents/XPCServices/ all’interno del bundle dell’applicazione. Puoi cercare nella tua directory /Applications e vedere quante applicazioni si affidano ai servizi XPC.
Puoi anche avere servizi XPC all’interno di Frameworks (che sono un altro tipo di Bundle).
Benefici aggiuntivi dei servizi XPC
L’utilizzo dei servizi XPC nelle nostre applicazioni ci permette di spezzare alcune funzionalità in moduli separati (il servizio XPC). Potremmo creare un servizio XPC che può essere incaricato di eseguire alcuni compiti costosi ma poco frequenti. Per esempio, qualche compito di crittografia per generare numeri casuali.
Un altro vantaggio aggiuntivo è che il servizio XPC viene eseguito su un proprio processo. Se questo processo si blocca o viene ucciso, non influisce sulla nostra applicazione principale. Immaginate che la vostra applicazione supporti plugin definiti dall’utente. E i plugin sono costruiti usando i servizi XPC. Se sono codificati male e vanno in crash, non influiranno sull’integrità della vostra applicazione principale.
Un ulteriore vantaggio del servizio XPC è che possono avere i propri diritti. L’applicazione richiederà il diritto solo quando farà uso di un servizio fornito da XPC Service che richiede il diritto. Immaginate di avere un’applicazione che usa la localizzazione ma solo per funzioni specifiche. Potreste spostare queste funzioni in un servizio XPC e aggiungere il diritto di localizzazione solo a quel servizio XPC. Se il vostro utente non ha mai bisogno della funzione che usa la localizzazione, non gli verranno richieste le autorizzazioni, rendendo l’uso della vostra app più affidabile.
XPC e il nostro amico launchd
launchd è il primo processo a girare sul nostro sistema. Si occupa di lanciare e gestire altri processi, servizi e demoni. launchd si occupa anche di programmare i compiti. Quindi ha senso che launchd sia anche responsabile della gestione dei servizi XPC.
Il servizio XPC può essere fermato se è stato inattivo per molto tempo, o essere generato su richiesta. Tutta la gestione è fatta da launchd, e non abbiamo bisogno di fare nulla perché funzioni.
launchd ha informazioni sulla disponibilità di risorse a livello di sistema e sulla pressione della memoria, chi meglio di launchd può prendere decisioni su come utilizzare al meglio le risorse del nostro sistema
Implementare i servizi XPC
Un servizio XPC è un bundle nella directory Contents/XPCServices del bundle dell’applicazione principale; il bundle del servizio XPC contiene un file Info.plist, un eseguibile e qualsiasi risorsa necessaria al servizio. Il servizio XPC indica quale funzione chiamare quando il servizio riceve messaggi chiamando xpc_main(3) Mac OS X Developer Tools Manual Page dalla sua funzione principale.
Per creare un servizio XPC in Xcode, fai come segue:
- Aggiungi un nuovo obiettivo al tuo progetto, usando il modello XPC Service.
- Aggiungi una fase Copy Files alle impostazioni di compilazione della tua applicazione, che copia il servizio XPC nella directory Contents/XPCServices del bundle principale dell’applicazione.
- Aggiungi una dipendenza alle impostazioni di compilazione della tua applicazione, per indicare che dipende dal bundle del servizio XPC.
- Se stai scrivendo un servizio XPC di basso livello (basato su C), implementa una funzione principale minima per registrare il tuo gestore di eventi, come mostrato nel seguente codice. Sostituite my_event_handler con il nome della vostra funzione gestore di eventi.
int main(int argc, const char *argv) {
xpc_main(my_event_handler);
// The xpc_main() function never returns.
exit(EXIT_FAILURE);
}
Se state scrivendo un servizio di alto livello (basato su Objective-C) usando NSXPCConnection, create prima una classe delegata di connessione conforme al protocollo NSXPCListenerDelegate. Poi, implementa una funzione principale minima che crea e configura un oggetto ascoltatore, come mostrato nel seguente elenco di codice.
int main(int argc, const char *argv) {
MyDelegateClass *myDelegate = ...
NSXPCListener *listener =
;
listener.delegate = myDelegate;
;
// The resume method never returns.
exit(EXIT_FAILURE);
}
Usare il servizio
Il modo in cui usi un servizio XPC dipende dal fatto che tu stia lavorando con l’API C (XPC Services) o l’API Objective-C (NSXPCConnection).
Utilizzare l’API Objective-C NSXPCConnection L’API Objective-C NSXPCConnection fornisce un’interfaccia di chiamata di procedura remota di alto livello che permette di chiamare metodi su oggetti in un processo da un altro processo (di solito un’applicazione che chiama un metodo in un servizio XPC). L’API NSXPCConnection serializza automaticamente le strutture dati e gli oggetti per la trasmissione e li deserializza all’altro capo. Di conseguenza, chiamare un metodo su un oggetto remoto si comporta come chiamare un metodo su un oggetto locale.
Per utilizzare l’API NSXPCConnection, è necessario creare quanto segue:
- Un’interfaccia. Questa consiste principalmente in un protocollo che descrive quali metodi dovrebbero essere richiamabili dal processo remoto. Questo è descritto in Progettare un’interfaccia
- Un oggetto di connessione su entrambi i lati. Dal lato del servizio, questo è stato descritto in precedenza in Creare il servizio. Sul lato client, questo è descritto in Connecting to and Using an Interface.
- Un ascoltatore. Questo codice nel servizio XPC accetta le connessioni. Questo è descritto in Accettare una connessione nell’Helper. Messages.