ProtocolBuffers
Swift
gRPC
grpc-swift

grpc-swiftを使う準備を整える

grpc-swiftを見ながら。最低限の通信をするMacアプリのサーバー、iPhoneアプリのクライアント作成を試してみたので手順を記録します。

環境

  • cocoapods 1.5.0
  • Xcode 9.3
  • Homebrew 1.6.3
  • SwiftGRPC: 0.4.3
  • protoc --version libprotoc 3.5.1
  • protoc-gen-swift --version protoc-gen-swift 1.0.3

Protocol Buffer Compilerのインストール

protobufをhomebrewでインストールします。

$ brew install protobuf

これでProtocol Buffer Compiler(以下protoc)がインストールされました。

$ protoc --version
$ libprotoc 3.5.1

Swift用のprotocプラグインの準備

まずはgrpc-swiftリポジトリをクローンします。

$ git clone https://github.com/grpc/grpc-swift.git

クローン後のディレクトリ(以下ディレクトリルート)でmakeを叩きます。

$ cd grpc-swift
$ make

これでSwift Package Managerによる依存パッケージのビルドが実行され、protocのプラグインprotoc-gen-swift(.protoファイルからSwiftコードを生成する)とprotoc-gen-swiftgrpc(gRPCに対応したコードを生成する)がディレクトリルートにコピーされています。(下記はただのコピーされた状態の確認です。)

$ ls | grep protoc
protoc-gen-swift
protoc-gen-swiftgrpc

生成されたプラグインを/usr/local/binにコピーします。

$ cp protoc-gen-swift protoc-gen-swiftgrpc /usr/local/bin

試しに適当なprotoファイルをコンパイルしてみます。
helloworld.protoという名前のファイルを作成して、以下内容に編集してから保存します。

helloworld.proto
syntax = "proto3";

package greeter;

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}

保存したら下記コマンドを実行してみてください。
helloworld.pb.swiftとhelloworld.grpc.swiftが生成されていれば、protocプラグインのインストールは完了です。

protoc helloworld.proto --swift_out=. --swiftgrpc_out=.

実プロジェクトにgrpc-swiftを導入する。

grpc-swift0.42からcocoapodsに対応したようです。 :tada:
なのでそれを使います。

$ sudo gem install cocoapods`

新規でXcodeプロジェクトを作成し、プロジェクトのディレクトリ直下でpod initします。

エディタでPodfileを開き、pod 'SwiftGRPC'の行を加えて、pod installを実行します。

# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'

target 'gRPC-Sample' do
  # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
  use_frameworks!

  # Pods for gRPC-Sample
  pod 'SwiftGRPC'

  target 'gRPC-SampleTests' do
    inherit! :search_paths
    # Pods for testing
  end

  target 'gRPC-SampleUITests' do
    inherit! :search_paths
    # Pods for testing
  end

end

pod installすると下記の依存関係がインストールされます。

Installing BoringSSL (10.0.2)
Installing SwiftGRPC (0.4.2)
Installing SwiftProtobuf (1.0.3)
Installing gRPC-Core (1.11.0)
Installing nanopb (0.3.8)

サーバーでは、下記のように自動生成されたprotocolを実装します。

final class GreeterProvider: Greeter_GreeterProvider {
    func sayHello(request: Greeter_HelloRequest, session: Greeter_GreeterSayHelloSession) throws -> Greeter_HelloReply {
        var g = Greeter_HelloReply()
        g.message = request.name + " world"
        return g
    }
}

クライアントでは、下記のように自動生成されたfinalなクライアントクラスを実装します。
これで最低限通信するサンプルが実装できました。

 let client = Greeter_GreeterServiceClient.init(address: "127.0.0.1:50051", secure: false)
        var request = Greeter_HelloRequest()
        request.name = "hello"
        let ret = try? client.sayHello(request)
        print("gRPC Server returns " + ret!.message)

ここまでのコードは一応こちらに上げてあります。 https://github.com/tikidunpon/gRPC-Swift-Sample

また、grpc-swiftのリポジトリにcocoapodsを使ってGoogle Cloud Natural Language APIを叩くサンプルもあるようなので、GCPのアカウントを持っているかたは試してみてはいかがでしょうか?