macOS XPC(Client) With Swift

ponyo721._.·2025년 2월 8일
post-thumbnail

XPC Client Calss


import Foundation

protocol XPCClientUtilDelegate {
    func recvXPCDisconnectEvent()
}

class XPCClientUtil: NSObject {
    //MARK: - Public Variables
    var listener: NSXPCListener?
    var connection: NSXPCConnection?
    
    var clientReciver:XPCClientImpl = XPCClientImpl()
    
    //MARK: - Public Methods
    
    /// Start a new XPC connection.
    func start() {
        NSLog("[XPCClientUtil] start.")
        
        connection = NSXPCConnection(
            machServiceName: "com.ponyo.macos.XPCServerWithSwift"
        )
        
        // 3. 내 Process가 Recv할 Func Protocol 지정
        connection!.exportedInterface = NSXPCInterface(
            with: XPCClientProtocol.self
        )
        
        // 4. 3번에서 지정한 func이 호출되면 실제 정의된 곳으로 전달해달 요청
        connection!.exportedObject = clientReciver
        
        // 연결된 다른 프로세스에게 보낼 프로토콜
        connection!.remoteObjectInterface = NSXPCInterface(
            with: XPCServerProtocol.self
        )
        
        // 6. XPC연결이 끊어졌을 때 호출될 함수 지정
        connection!.invalidationHandler = connectionInvalidationHandler
        connection!.interruptionHandler = connetionInterruptionHandler
        
        NSLog("[XPCClientUtil] resume")
        connection?.resume()

        clientReciver.server = connection?.remoteObjectProxy as? XPCServerProtocol
        clientReciver.server?.printHello()
    }
    
    func xpcDisconnect() {

    }
    
    //MARK: - XPC Disconnect callback -
    
    /// XPC session interruption handler
    private func connetionInterruptionHandler() {
        NSLog("[XPCClientUtil] \(type(of: self)): connection has been interrupted.")

    }
    
    /// XPC session invalidation handler
    private func connectionInvalidationHandler() {
        NSLog("[XPCClientUtil] \(type(of: self)): connection has been invalidated.")
    }
    
    //MARK: - XPC Commmon Private Func -
    
    //MARK: - XPC Commmon Public Func -
    
    func sendHello() {
        clientReciver.server?.printHello()
    }
}

XPC Protocol Class


import Foundation

//MARK: - XPCClientProtocol -
// target process가 내 process로 보내는 요청
@objc(XPCClientProtocol)
protocol XPCClientProtocol {
    func printClientHello()
    func sendJSONData(_ jsonData: Data, withReply reply: @escaping (Data?) -> Void)
}

//MARK: - XPC Recv Func Implementation -
class XPCClientImpl:NSObject, XPCClientProtocol {
    var server:XPCServerProtocol? = nil
    
    func printClientHello() {
        print("Server Hello")
    }
    
    
    func sendJSONData(_ jsonData: Data, withReply reply: @escaping (Data?) -> Void) {
        do {
            let decoder = JSONDecoder()
            let user = try decoder.decode(User.self, from: jsonData)
            print("Received User Object:")
            print("ID: \(user.id), Name: \(user.name), Email: \(user.email)")
            
            // 응답으로 새로운 User 객체를 전송
            let responseUser = User(id: user.id + 1, name: "Reply to \(user.name)", email: user.email)
            let encoder = JSONEncoder()
            let responseData = try encoder.encode(responseUser)
            reply(responseData)
        } catch {
            print("Failed to process JSON data:", error)
            reply(nil)
        }
    }
}


//MARK: - XPCServerProtocol -
@objc(XPCServerProtocol)
protocol XPCServerProtocol {
    func printHello()
}

//MARK: - XPC Recv Func Implementation -
class XPCServerImpl:NSObject, XPCServerProtocol {
    var client:XPCClientProtocol? = nil
    
    func printHello() {
        print("Client Hello")
    }
}

Data Model Class

import Foundation

// Codable을 채택한 데이터 클래스
class User: Codable {
    var id: Int
    var name: String
    var email: String

    init(id: Int, name: String, email: String) {
        self.id = id
        self.name = name
        self.email = email
    }
}

Call Process

@main
let xpcClient:XPCClientUtil = XPCClientUtil()
xpcClient.start()
xpcClient.sendHello()
profile
macOS Native Application Developer

0개의 댓글