gRPC для Swift (iOS/macOS): библиотеки, настройка и примеры кода

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

gRPC для Swift (iOS/macOS): библиотеки и примеры

gRPC — это современный высокопроизводительный фреймворк для удалённого вызова процедур (RPC), разработанный Google. Он использует Protocol Buffers (protobuf) для сериализации данных и HTTP/2 для транспорта. В экосистеме Swift (iOS/macOS) gRPC реализован через библиотеку gRPC-Swift, построенную поверх асинхронного фреймворка SwiftNIO. Это позволяет создавать как клиентские, так и серверные приложения на Swift с поддержкой потоковой передачи данных, таймаутов и аутентификации.

Основные библиотеки для gRPC в Swift

  • gRPC-Swift — официальная библиотека от Apple и Google. Предоставляет API для создания gRPC-серверов и клиентов. Поддерживает унарные, серверные, клиентские и двунаправленные потоки.
  • SwiftNIO — низкоуровневый асинхронный фреймворк для сетевого взаимодействия, на котором основан gRPC-Swift.
  • protoc-gen-swiftgrpc — плагин для компилятора protoc, генерирующий Swift-код из .proto файлов.
  • SwiftProtobuf — библиотека для работы с protobuf-сообщениями в Swift (сериализация/десериализация).

Установка через Swift Package Manager

Добавьте зависимости в Package.swift вашего проекта:

// swift-tools-version:5.7
import PackageDescription

let package = Package(
    name: "gRPCExample",
    platforms: [.macOS(.v12), .iOS(.v15)],
    dependencies: [
        .package(url: "https://github.com/grpc/grpc-swift.git", from: "1.21.0"),
        .package(url: "https://github.com/apple/swift-protobuf.git", from: "1.21.0")
    ],
    targets: [
        .executableTarget(
            name: "gRPCExample",
            dependencies: [
                .product(name: "GRPC", package: "grpc-swift"),
                .product(name: "SwiftProtobuf", package: "swift-protobuf")
            ]
        )
    ]
)

Создание .proto файла

Определите сервис и сообщения. Пример файла helloworld.proto:

syntax = "proto3";

service Greeter {
    rpc SayHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
    string name = 1;
}

message HelloReply {
    string message = 1;
}

Генерация Swift-кода

Установите protoc и плагины:

brew install protobuf
brew install swift-protobuf
brew install grpc-swift

Сгенерируйте код:

protoc helloworld.proto \
    --proto_path=. \
    --swift_out=. \
    --grpc-swift_out=.

Будут созданы файлы helloworld.pb.swift и helloworld.grpc.swift.

Пример сервера на Swift (macOS)

import GRPC
import NIO
import HelloWorld // сгенерированный модуль

class GreeterProvider: Greeter_GreeterProvider {
    func sayHello(request: Greeter_HelloRequest, context: StatusOnlyCallContext) -> EventLoopFuture<Greeter_HelloReply> {
        var reply = Greeter_HelloReply()
        reply.message = "Привет, \(request.name)!"
        return context.eventLoop.makeSucceededFuture(reply)
    }
}

let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
defer { try! group.syncShutdownGracefully() }

let server = try Server.insecure(group: group)
    .withServiceProviders([GreeterProvider()])
    .bind(host: "localhost", port: 50051)
    .wait()

print("Сервер запущен на localhost:50051")
try server.onClose.wait()

Пример клиента на Swift (iOS/macOS)

import GRPC
import NIO
import HelloWorld

let group = PlatformSupport.makeEventLoopGroup(loopCount: 1)
defer { try! group.syncShutdownGracefully() }

let channel = try GRPCChannelPool.with(
    target: .host("localhost", port: 50051),
    transportSecurity: .plaintext,
    eventLoopGroup: group
)
defer { try! channel.close().wait() }

let client = Greeter_GreeterClient(channel: channel)

var request = Greeter_HelloRequest()
request.name = "Мир"

let call = client.sayHello(request)
let response = try call.response.wait()
print("Ответ сервера: \(response.message)")

Особенности для iOS

  • Для iOS требуется iOS 15+ из-за зависимостей от async/await и SwiftNIO.
  • В реальных приложениях используйте async

Рекомендаций