XPC servislerini yapılandırma, istemci oturumları oluşturma ve süreçler arasında mesaj alışverişi.
XPC Servisleri Oluşturma
Makale | XPC
Bir dinleyici yapılandırın, istemci oturumu kurun ve süreçler arasında mesaj alışverişi yapın.
XPC servislerinin iki tarafı vardır: gelen bağlantıları kabul edip görevleri gerçekleştiren bir dinleyici (sunucu) ve bağlantı başlatıp istekler yapan bir istemci. Aşağıdaki örnek iki sayıyı toplayan bir servisi göstermektedir.
XPC Servisi Hedefi Ekleme
XPC Service şablonu, bir XPC bağlantısının dinleyici tarafını oluşturmak için bir başlangıç noktası sağlar. Bir hedef eklemek için:
1. Xcode'da uygulamanızı veya çerçeve projenizi açın. 2. File > New > Target'ı seçin. 3. Framework & Library bölümünden XPC Service'i seçin. 4. Next'e tıklayın. 5. Servisin adını belirtin. 6. API Level açılır menüsünden Low Level - libXPC'yi seçin. 7. Finish'e tıklayın.
Önemli: Ad ve API seviyesini girdiğinizde gösterilen paket tanımlayıcı (bundle identifier) değerini not edin. İstemciler servise bağlanmak için bu değeri kullanır.
Dinleyici Oluşturma
launchd bir XPC servisini başlattığında, servisin ikili dosyasını çalıştıran bir süreç başlatır. Görev gerçekleştirmek için servis, bir servis adıyla ve gelen oturum isteklerini işleyen bir kapatma (closure) ile bir XPCListener oluşturur. Uygulamanın veya çerçevenin paketindeki servisler için servis adı, XPC servisinin paket tanımlayıcısıdır. XPCListener oluşturduktan sonra, istekleri işlemeye başlamak için dispatchMain()) çağrılmalıdır.
Bir istemci servisle her oturum başlattığında, sistem dinleyicinin kapatmasını çağırır ve bir XPCListener.IncomingSessionRequest iletir. Dinleyici isteği kabul eder veya reddeder. Kabul ederse, istemcinin gönderdiği mesajı almak için bir istek işleme kapatması sağlar.
let serviceName = "com.example.XPC-Calc-Engine"
let listener = try XPCListener(service: serviceName) { request in
request.accept { message in
performCalculation(with: message)
}
}
dispatchMain()
Dinleyici isteği reddederse, istemciye reddetme nedenini açıklayan bir reason dizesi sağlar:
// Bir istek işlenemezse, gelen isteği reddet.
request.reject(reason: "Servis kullanılamıyor.")
Görev Gerçekleştirme
İstemciler özel bir Codable tipi göndererek istekte bulunur. Servis gelen mesajı çözer, görevi gerçekleştirir ve yanıtı döndürür:
// Toplanacak iki sayıyı içeren kodlanabilir tip.
struct CalculationRequest: Codable {
let firstNumber: Int
let secondNumber: Int
}
// Hesaplama sonucunu içeren kodlanabilir tip.
struct CalcuationResponse: Codable {
let result: Int
}
func performCalculation(with message: XPCReceivedMessage) -> Encodable? {
guard let request = try? message.decode(as: CalculationRequest.self) else { return nil }
return CalcuationResponse(result: request.firstNumber + request.secondNumber)
}
İstemci Oturumu Oluşturma
İstemci bir XPC servisi kullanmak istediğinde, servisle bir oturum oluşturur ve ardından mesaj gönderir:
let serviceName = "com.example.XPC-Calc-Engine"
let session = try XPCSession(xpcService: serviceName)
// İki sayıyla bir istek oluştur.
let request = CalculationRequest(firstNumber: 23, secondNumber: 19)
// Mesajı sunucuya gönder ve senkron yanıt bekle.
let reply = try session.sendSync(request)
if let response = try? reply.decode(as: CalcuationResponse.self) {
// Sonuçla bir işlem yap, örneğin UI'da göster.
let result = response.result
}
XPCListener
Sınıf | XPC
*iOS 17.0+, iPadOS 17.0+, Mac Catalyst 17.0+, macOS 14.0+, tvOS 17.0+, watchOS 10.0+*
Süreç sınırları boyunca istemciler için görevler gerçekleştiren tip.
class XPCListener
Bir XPC servisi uygulamak için bir dinleyici oluşturun ve gelen oturum isteklerine yanıt verin.
Dinleyici Oluşturma
Dinleyici oluşturmak için birden fazla başlatıcı (initializer) mevcuttur. Hedeflenen kullanım senaryosuna göre seçilir:
| Başlatıcı | Kullanım Senaryosu | | --- | --- | | init(service:handlerQueue:options:incomingSessionHandler:) | XPC servisi paketi için dinleyici | | init(machService:handlerQueue:options:incomingSessionHandler:) | Mach servisi için dinleyici | | init(forCurrentProcess:handlerQueue:options:incomingSessionHandler:) | Geçerli süreç için anonim dinleyici |
Başlatıcı imzaları:
// XPC servisi için
init(service: String,
handlerQueue: DispatchQueue? = nil,
options: XPCListener.InitializationOptions = .none,
incomingSessionHandler: @escaping @Sendable (XPCListener.IncomingSessionRequest) -> XPCListener.IncomingSessionRequest.Decision) throws
// Mach servisi için
init(machService: String,
handlerQueue: DispatchQueue? = nil,
options: XPCListener.InitializationOptions = .none,
incomingSessionHandler: @escaping @Sendable (XPCListener.IncomingSessionRequest) -> XPCListener.IncomingSessionRequest.Decision) throws
// Anonim dinleyici
init(forCurrentProcess options: XPCListener.InitializationOptions = .none,
handlerQueue: DispatchQueue? = nil,
incomingSessionHandler: @escaping @Sendable (XPCListener.IncomingSessionRequest) -> XPCListener.IncomingSessionRequest.Decision)
XPCPeerHandler protokolü ile oluşturma:
// XPCPeerHandler kullanan varyantlar da mevcuttur:
init<Handler>(service: String, handler: Handler.Type,
handlerQueue: DispatchQueue? = nil,
options: XPCListener.InitializationOptions = .none) throws
where Handler : XPCPeerHandler
Yaşam Döngüsü Yönetimi
func activate()— Yeni oturum isteklerini kabul etmeye başlamak için etkinleştirir.func cancel()— Mevcut tüm bağlantıları keserek dinleyiciyi iptal eder.var endpoint: XPCEndpoint— Başka süreçlere iletilebilen serileştirilmiş dinleyici uç noktası.
Önemli: inactive seçeneğiyle oluşturulan dinleyiciler, activate() çağrılana kadar oturum isteklerini almaz.
InitializationOptions
Dinleyici oluşturma seçenekleri:
static let none: XPCListener.InitializationOptions— Varsayılan yapılandırma.static let inactive: XPCListener.InitializationOptions— Oluşturma sırasında etkinleştirilmez;activate()ile manual etkinleştirme gerekir.
IncomingSessionRequest
Bir istemciden gelen oturum isteğini temsil eder. Dinleyicinin kapatması bu parametreyi alır ve kabul/reddetme kararı döndürür.
İsteği kabul etme:
// Basit kabul — Decodable mesaj handler ile
func accept<Message>(_ incomingMessageHandler:
@escaping @Sendable (Message) -> (any Encodable)?)
-> XPCListener.IncomingSessionRequest.Decision
where Message : Decodable
// XPCReceivedMessage handler ile kabul
func accept(_ incomingMessageHandler:
@escaping @Sendable (XPCReceivedMessage) -> (any Encodable)?)
-> XPCListener.IncomingSessionRequest.Decision
// XPCDictionary handler ile kabul
func accept(_ incomingMessageHandler:
@escaping @Sendable (XPCDictionary) -> XPCDictionary?)
-> XPCListener.IncomingSessionRequest.Decision
// İptal handler'ı ile birlikte kabul (6 varyant)
func accept(incomingMessageHandler:..., cancellationHandler:...)
-> XPCListener.IncomingSessionRequest.Decision
İsteği reddetme:
func reject(reason: String) -> XPCListener.IncomingSessionRequest.Decision
Eş doğrulama gereksinimleri:
func setPeerRequirement(_ requirement: XPCPeerRequirement)
// Mac Catalyst 26.0+, macOS 26.0+
XPCPeerHandler Protokolü
Bir alternatif olarak, closure tabanlı yaklaşım yerine XPCPeerHandler protokolünü uygulayabilirsiniz:
protocol XPCPeerHandler
// Gerekli üyeler:
associatedtype Input // İstemciden gelen mesaj tipi
associatedtype Output // Yanıt mesaj tipi
func handleIncomingRequest(_: Self.Input) -> Self.Output?
func handleCancellation(error: XPCRichError) // Varsayılan uygulaması var
Uyum (Conformances)
Sendable,SendableMetatype
XPCSession
Sınıf | XPC
*iOS 17.0+, iPadOS 17.0+, macOS 14.0+, tvOS 17.0+, watchOS 10.0+*
Bir sunucu sürecine mesaj gönderen tip.
class XPCSession
Oturum Oluşturma
XPC servisleri, Mach servisleri veya uç noktalar (endpoint) aracılığıyla oturum oluşturulabilir:
// XPC servisiyle oturum (çeşitli varyantlar)
init(xpcService: String, targetQueue: DispatchQueue? = nil,
options: XPCSession.InitializationOptions = .none,
incomingMessageHandler: ...,
cancellationHandler: ...) throws
// Mach servisiyle oturum
init(machService: String, targetQueue: DispatchQueue? = nil,
options: XPCSession.InitializationOptions = .none,
incomingMessageHandler: ...,
cancellationHandler: ...) throws
// Uç noktayla oturum
init(endpoint: XPCEndpoint, targetQueue: DispatchQueue? = nil,
options: XPCSession.InitializationOptions = .none,
cancellationHandler: ...) throws
incomingMessageHandler, üç farklı mesaj tipini destekleyen aşırı yüklemelere (overload) sahiptir: Decodable jenerik tip, XPCReceivedMessage ve XPCDictionary.
InitializationOptions
Oturum oluşturma seçenekleri:
static let none: XPCSession.InitializationOptions— Varsayılan yapılandırma.static let inactive: XPCSession.InitializationOptions— Oluşturma sırasında etkinleştirilmez.static let privileged: XPCSession.InitializationOptions— Mach servisinin ayrıcalıklı Mach bootstrap'ında olduğunu belirtir.
Önemli: inactive ile oluşturulan oturumlar, mesaj göndermeden önce activate() ile etkinleştirilmelidir.
Mesaj Gönderme
Oturumlar mesajları seri olarak, ilk giren ilk çıkar (FIFO) sırasıyla gönderir. Bu yöntemler birden fazla dispatch kuyruğundan çağrılabilir.
Tek yönlü gönderme (yanıt beklemeden):
func send<Message>(_ message: Message) throws where Message : Encodable
func send(message: XPCDictionary) throws
Yanıtlı asenkron gönderme:
func send<Message>(_ message: Message,
replyHandler: @escaping @Sendable (Result<XPCReceivedMessage, XPCRichError>) -> Void) throws
where Message : Encodable
func send<Message, Reply>(_ message: Message,
replyHandler: @escaping @Sendable (Result<Reply, any Error>) -> Void) throws
where Message : Encodable, Reply : Decodable
func send(message: XPCDictionary,
replyHandler: @escaping @Sendable (Result<XPCDictionary, XPCRichError>) -> Void)
Senkron gönderme (çağıranı yanıt gelene kadar bloklar):
func sendSync<Message, Reply>(_ message: Message) throws -> Reply
where Message : Encodable, Reply : Decodable
func sendSync<Message>(_ message: Message) throws -> XPCReceivedMessage
where Message : Encodable
func sendSync(message: XPCDictionary) throws -> XPCDictionary
Önemli: inactive bir oturumdayken mesaj gönderme çağrısı *çöküşe* (crash) neden olur!
Yaşam Döngüsü Yönetimi
func activate() // Oturumu etkinleştir
func cancel(reason: String) // Belirtilen nedenle iptal et
func setCancellationHandler(_ handler: ...) // İptal kapatmasını ayarla
func setIncomingMessageHandler(_ handler: ...) // Gelen mesaj kapatmasını ayarla
func setTargetQueue(_ targetQueue: DispatchQueue) // Hedef kuyruğu ayarla
func setPeerRequirement(_ req: XPCPeerRequirement) // Eş gereksinimleri ayarla
Önemli: setCancellationHandler, setIncomingMessageHandler ve setTargetQueue yalnızca etkin olmayan oturumlarda çağrılmalıdır.
Uyum (Conformances)
Sendable,SendableMetatype
XPCReceivedMessage
Yapı (Struct) | XPC
*iOS 17.0+, iPadOS 17.0+, macOS 14.0+, tvOS 17.0+, watchOS 10.0+*
Bir oturum ile dinleyici arasında gönderilen mesajı temsil eden tip.
struct XPCReceivedMessage
Mesaj İçeriğine Erişim
// Mesajı kodlanabilir tipe çöz
func decode<T>(as: T.Type) throws -> T where T : Decodable
// Alt mesaj sözlüğüne eriş
var dictionary: XPCDictionary { get }
Gönderen Bilgilerine Erişim
var senderAuditToken: audit_token_t { get }
Gönderen sürecin denetim belirtecini (audit token) döndürür. Bu belirteç, gönderenin yetkilendirme (authorization) ve ayrıcalıklarını doğrulamak için kullanılabilir.
Uyum (Conformances)
Copyable,CustomDebugStringConvertible,Escapable,Sendable,SendableMetatype
XPC Güncellemeleri
Makale | Updates
XPC'deki önemli değişiklikler hakkında bilgi edinin.
macOS 26 / iOS 26 Yenilikleri
- Bir XPC bağlantısı üzerinden iletişim kuran eş yürütülebilir dosyanın belirli bir yetkilendirmeye (entitlement) sahip olup olmadığını test etmek için yeni fonksiyonlar:
xpc_connection_set_peer_entitlement_exists_requirement(_:_:)xpc_connection_set_peer_entitlement_matches_value_requirement(_:_:_:)- Eş yürütülebilir dosyanın bir Apple platform ikili dosyası olup olmadığını test etme:
xpc_connection_set_peer_platform_identity_requirement(_:_:) - Aynı Apple Developer takımı tarafından imzalanıp imzalanmadığını test etme:
xpc_connection_set_peer_team_identity_requirement(_:_:) - Hafif kod gereksinimi (lightweight code requirement) kontrolü:
xpc_connection_set_peer_lightweight_code_requirement(_:_:)
macOS 14 / iOS 17 Yenilikleri
- Swift için yerel XPC API: XPCListener ile sunucu, XPCSession ile istemci oluşturma.
- C ve Objective-C projeleri için xpc_listener_t ve xpc_session_t API'leri.
- Xcode'da güncellenmiş XPC servisleri hedef şablonu: NSXPCConnection (yüksek seviye) veya libXPC (düşük seviye) arasında seçim yapabilme.