LoginSignup
26
21

More than 3 years have passed since last update.

Xcode(Swift) + CocoaPodsでgRPCのClientを生成してServiceを呼び出すまでの流れ

Last updated at Posted at 2016-08-24

About

iOSアプリからgRPCのServiceを呼び出す実験をしてみようと思ったのですが、CocoaPodsを利用した導入についての情報が意外とまとまっていなかったので、その流れをまとめておきます。

Protocol Buffersの定義から、Clientライブラリが自動的に生成される様子をお楽しみ下さい。

前提

プロジェクト名をGrpcMobileDemoとし、以下のような構成からスタートすることを想定します。

.
├── GrpcMobileDemo
├── GrpcMobileDemo.xcodeproj
├── GrpcMobileDemo.xcworkspace
├── Podfile
└── Pods

流れ

1. ローカルにgRPC ClientのPodを定義する

仕組みは後述するとして、gRPC Serviceに対するClientとして機能するPodを、ローカルに定義します。

  • RemoteClientという名前でディレクトリを作成し、podspecとgRPCのサービスが定義されたprotoを配置します。
    • ここではRemoteClientという名前にしましたが、名前は自由です。衝突しないお好きな名前をどうぞ。
.
├── GrpcMobileDemo
├── GrpcMobileDemo.xcodeproj
├── GrpcMobileDemo.xcworkspace
├── Podfile
├── Pods
└── RemoteClient
    ├── RemoteClient.podspec
    └── helloworld.proto

RemoteClient.podspecは次のような内容です。authorshomepageなどは、ご自身の値を設定して下さい。

RemoteClient/RemoteClient.podspec
Pod::Spec.new do |s|
  s.name     = 'RemoteClient'
  s.version  = '0.0.1'
  s.license  = 'MIT'
  s.authors  = { '<your user name>' => '<your email address>' }
  s.homepage = '<your homepage>'
  s.summary = 'gRPC test client'
  s.source = { :git => '<your git repository>' }

  s.ios.deployment_target = '7.1'
  s.osx.deployment_target = '10.9'

  # Run protoc with the Objective-C and gRPC plugins to generate protocol messages and gRPC clients.
  s.dependency "!ProtoCompiler-gRPCPlugin", "~> 1.0.0"

  # Pods directory corresponding to this app's Podfile, relative to the location of this podspec.
  pods_root = '../Pods'

  # Path where Cocoapods downloads protoc and the gRPC plugin.
  protoc_dir = "#{pods_root}/!ProtoCompiler"
  protoc = "#{protoc_dir}/protoc"
  plugin = "#{pods_root}/!ProtoCompiler-gRPCPlugin/grpc_objective_c_plugin"

  s.prepare_command = <<-CMD
    #{protoc} \
        --plugin=protoc-gen-grpc=#{plugin} \
        --objc_out=. \
        --grpc_out=. \
        -I . \
        -I #{protoc_dir} \
        *.proto
  CMD

  s.subspec 'Messages' do |ms|
    ms.source_files = '*.pbobjc.{h,m}'
    ms.header_mappings_dir = '.'
    ms.requires_arc = false
    ms.dependency 'Protobuf'
    # This is needed by all pods that depend on Protobuf:
    ms.pod_target_xcconfig = {
      'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1',
    }
  end

  s.subspec 'Services' do |ss|
    ss.source_files = '*.pbrpc.{h,m}'
    ss.header_mappings_dir = '.'
    ss.requires_arc = true
    ss.dependency 'gRPC-ProtoRPC'
    ss.dependency "#{s.name}/Messages"
  end
end

gRPCのサービスとして、gRPCのサンプルにあるhelloworld.protoを写経したものを配置してみました。

RemoteClient/helloworld.proto
syntax = "proto3";

option java_multiple_files = true;
option java_package = "com.hosopy.grpcdemo.helloworld";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";

package helloworld;

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

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

2. 定義したPodをPodfileで参照する

先ほど定義したローカルのPodを、Podfileで参照します。

Podfile
target 'GrpcMobileDemo' do
  # Comment this line if you're not using Swift and don't want to use dynamic frameworks
  use_frameworks!

  # Pods for GrpcMobileDemo
  pod 'RemoteClient', path: './RemoteClient'

  target 'GrpcMobileDemoTests' do
    inherit! :search_paths
    # Pods for testing
  end

  target 'GrpcMobileDemoUITests' do
    inherit! :search_paths
    # Pods for testing
  end

end

3. pod install

あとはpod installするだけで完了です。

$ pod install

RemoteClient/RemoteClient.podspecで定義されたprepare_commandによって、pod installのプロセスでprotocが自動的に実行され、Objective-Cのファイルが自動生成されていることが分かります。

.
├── GrpcMobileDemo
├── GrpcMobileDemo.xcodeproj
├── GrpcMobileDemo.xcworkspace
├── Podfile
├── Pods
└── RemoteClient
    ├── Helloworld.pbobjc.h
    ├── Helloworld.pbobjc.m
    ├── Helloworld.pbrpc.h
    ├── Helloworld.pbrpc.m
    ├── RemoteClient.podspec
    └── helloworld.proto

Xcodeのプロジェクトでもファイルが確認できますね。

xcode.png

4. Serviceの呼び出し

以上で準備は完了なので、あとは生成されたClientを利用してServiceを呼び出すだけです。
以下は、localhost:50051に非SSLで接続してServiceを呼び出すサンプルです。

GrpcMobileDemo/HelloWorldViewController.swift
import Foundation
import UIKit
import RemoteClient

class HelloWorldViewController: UIViewController {
    ...

    @IBAction func requestButtonPressed(sender: UIButton) {
        // For debug
        // 非SSLでの接続には必要
        GRPCCall.useInsecureConnectionsForHost("localhost:50051")

        // Call RPC
        let request = HLWHelloRequest()
        request.name = "neko"

        let client = HLWGreeter(host: "localhost:50051")
        client.sayHelloWithRequest(request) { response, error in
            // response is HLWHelloReply
            if let response = response {
                self.labelStatus.text = response.message
            } else {
                print("Error \(error)")
            }
        }
    }
}

なお、実験に使用したgRPCのサーバは、hosopy/grpc-mobile-demo-serverで公開していますが、Dockerですぐに起動できます。

$ docker run -i -t -p 50051:50051 hosopy/grpc-mobile-demo-server

参考

26
21
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
21