grpc.io/public/docs/quickstart/objective-c/index.html

446 lines
24 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="/css/style.css">
<title>
Objective-C Quickstart &ndash; gRPC
</title>
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
<link rel="manifest" href="/favicons/manifest.json">
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
<meta name="msapplication-TileColor" content="#ffffff">
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-60127042-1');
</script>
</head>
<body>
<div id="landing-content">
<div class="row">
<div class="topbannersub">
<nav class="navbar navbar-expand-md navbar-dark topnav">
<a class="navbar-brand" href="https://cjyabraham.github.io/">
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
<ul class="navbar-nav ml-auto">
<li class="nav-item ">
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
</li>
<li class="nav-item dropdown active">
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Docs
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
<a class="dropdown-item" href="/docs">
Overview
</a>
<a class="dropdown-item" href="/docs/quickstart/">
Quick Start
</a>
<a class="dropdown-item" href="/docs/guides/">
Guides
</a>
<a class="dropdown-item" href="/docs/tutorials/">
Tutorials
</a>
<a class="dropdown-item" href="/docs/reference/">
Reference
</a>
<a class="dropdown-item" href="/docs/samples/">
Samples
</a>
<a class="dropdown-item" href="/docs/talks">
Presentations
</a>
</div>
</li>
<li class="nav-item ">
<a class="nav-link" href="/blog">
Blog
</a>
</li>
<li class="nav-item ">
<a class="nav-link" href="/community">Community</a>
</li>
<li class="nav-item">
<a class="nav-link" href="https://packages.grpc.io/">
Packages
</a>
</li>
<li class="nav-item ">
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
</li>
</ul>
</div>
</nav>
<div class="headertext">Documentation</div>
</div>
</div>
</div>
<div class="subnav d-none d-md-block">
<a href="https://cjyabraham.github.io/docs/" >Overview</a>
| <a href="https://cjyabraham.github.io/docs/quickstart/" class="active">Quick Start</a>
| <a href="https://cjyabraham.github.io/docs/guides/" >Guides</a>
| <a href="https://cjyabraham.github.io/docs/tutorials/" >Tutorials</a>
| <a href="https://cjyabraham.github.io/docs/reference/" >Reference</a>
| <a href="https://cjyabraham.github.io/docs/samples/" >Samples</a>
| <a href="https://cjyabraham.github.io/docs/talks/" >Presentations</a>
</div>
<div class="quickstartcols">
<div class="quickstartcol1">
<h8>Quick Start</h8>
<a href="https://cjyabraham.github.io/docs/quickstart/cpp/" >C++</a>
<a href="https://cjyabraham.github.io/docs/quickstart/csharp/" >C#</a>
<a href="https://cjyabraham.github.io/docs/quickstart/dart/" >Dart</a>
<a href="https://cjyabraham.github.io/docs/quickstart/go/" >Go</a>
<a href="https://cjyabraham.github.io/docs/quickstart/java/" >Java</a>
<a href="https://cjyabraham.github.io/docs/quickstart/android/" >Android Java</a>
<a href="https://cjyabraham.github.io/docs/quickstart/node/" >Node.js</a>
<a href="https://cjyabraham.github.io/docs/quickstart/objective-c/" class="active">Objective-C</a>
<a href="https://cjyabraham.github.io/docs/quickstart/php/" >PHP</a>
<a href="https://cjyabraham.github.io/docs/quickstart/python/" >Python</a>
<a href="https://cjyabraham.github.io/docs/quickstart/ruby/" >Ruby</a>
<a href="https://cjyabraham.github.io/docs/quickstart/web/" >Web</a>
</div>
<div class="quickstartcol2" style="margin-top:4%">
<h3 style="margin-top:0px;">Objective-C Quickstart</h3>
<p class="lead">This guide gets you started with gRPC on the iOS platform in
Objective-C with a simple working example.</p>
<div id="toc"></div>
<h3 id="before-you-begin">Before you begin</h3>
<h4 id="system-requirement">System requirement</h4>
<p>The minimum deployment iOS version for gRPC is 7.0.</p>
<p>OS X El Capitan (version 10.11) or above is required to build and run this
Quickstart.</p>
<h4 id="prerequisites">Prerequisites</h4>
<ul>
<li><p><code>CocoaPods</code>: version 1.0 or higher</p>
<ul>
<li>Check status and version of CocoaPods on your system with command <code>pod
--version</code>.</li>
<li>If CocoaPods is not installed, follow the install instructions on CocoaPods
<a href="https://cocoapods.org">website</a>.</li>
</ul></li>
<li><p><code>Xcode</code>: version 7.2 or higher</p>
<ul>
<li>Check your Xcode version by running Xcode from Lauchpad, then select
&ldquo;Xcode-&gt;About Xcode&rdquo; in the menu.</li>
<li>Make sure the command line developer tools are installed:
<code>sh
[sudo] xcode-select --install
</code></li>
</ul></li>
<li><p><code>Homebrew</code></p>
<ul>
<li>Check status and version of Homebrew on your system with command <code>brew
--version</code>.</li>
<li>If Homebrew is not installed, install with:
<code>sh
/usr/bin/ruby -e &quot;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)&quot;
</code></li>
</ul></li>
<li><p><code>autoconf</code>, <code>automake</code>, <code>libtool</code>, <code>pkg-config</code></p>
<ul>
<li>Install with Homebrew
<code>sh
brew install autoconf automake libtool pkg-config
</code></li>
</ul></li>
</ul>
<h3 id="download-the-example">Download the example</h3>
<p>You&rsquo;ll need a local copy of the sample app source code to work through this
Quickstart. Copy the source code from GitHub
<a href="https://github.com/grpc/grpc">repository</a>:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">$ git clone --recursive -b v1.20.0 https://github.com/grpc/grpc.git</code></pre></div>
<h3 id="install-grpc-plugins-and-libraries">Install gRPC plugins and libraries</h3>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">$ cd grpc
$ make
$ <span style="color:#f92672">[</span>sudo<span style="color:#f92672">]</span> make install</code></pre></div>
<h3 id="install-protoc-compiler">Install protoc compiler</h3>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">$ brew tap grpc/grpc
$ brew install protobuf</code></pre></div>
<h3 id="run-the-server">Run the server</h3>
<p>For this sample app, we need a gRPC server running on the local machine. gRPC
Objective-C API supports creating gRPC clients but not gRPC servers. Therefore
instead we build and run the C++ server in the same repository:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">$ cd examples/cpp/helloworld
$ make
$ ./greeter_server &amp;</code></pre></div>
<h3 id="run-the-client">Run the client</h3>
<h4 id="generate-client-libraries-and-dependencies">Generate client libraries and dependencies</h4>
<p>Have CocoaPods generate and install the client library from our .proto files, as
well as installing several dependencies:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">$ cd ../../objective-c/helloworld
$ pod install</code></pre></div>
<p>(This might have to compile OpenSSL, which takes around 15 minutes if Cocoapods
doesn&rsquo;t have it yet on your computer&rsquo;s cache.)</p>
<h4 id="run-the-client-app">Run the client app</h4>
<p>Open the Xcode workspace created by CocoaPods:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">$ open HelloWorld.xcworkspace</code></pre></div>
<p>This will open the app project with Xcode. Run the app in an iOS simulator
by pressing the Run button on the top left corner of Xcode window. You can check
the calling code in <code>main.m</code> and see the results in Xcode&rsquo;s console.</p>
<p>The code sends a <code>HLWHelloRequest</code> containing the string &ldquo;Objective-C&rdquo; to a
local server. The server responds with a <code>HLWHelloResponse</code>, which contains a
string &ldquo;Hello Objective-C&rdquo; that is then output to the console.</p>
<p>Congratulations! You&rsquo;ve just run a client-server application with gRPC.</p>
<h3 id="update-a-grpc-service">Update a gRPC service</h3>
<p>Now let&rsquo;s look at how to update the application with an extra method on the
server for the client to call. Our gRPC service is defined using Protocol
Buffers; you can find out lots more about how to define a service in a <code>.proto</code>
file in Protocol Buffers
<a href="https://developers.google.com/protocol-buffers/">website</a>. For now all you
need to know is that both the server and the client &ldquo;stub&rdquo; have a <code>SayHello</code>
RPC method that takes a <code>HelloRequest</code> parameter from the client and returns a
<code>HelloResponse</code> from the server, and that this method is defined like this:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-c" data-lang="c"><span style="color:#75715e">// The greeting service definition.
</span><span style="color:#75715e"></span>service Greeter {
<span style="color:#75715e">// Sends a greeting
</span><span style="color:#75715e"></span> rpc SayHello (HelloRequest) returns (HelloReply) {}
}
<span style="color:#75715e">// The request message containing the user&#39;s name.
</span><span style="color:#75715e"></span>message HelloRequest {
string name <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;
}
<span style="color:#75715e">// The response message containing the greetings
</span><span style="color:#75715e"></span>message HelloReply {
string message <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;
}</code></pre></div>
<p>Let&rsquo;s update this so that the <code>Greeter</code> service has two methods. Edit
<code>examples/protos/helloworld.proto</code> and update it with a new <code>SayHelloAgain</code>
method, with the same request and response types:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-c" data-lang="c"><span style="color:#75715e">// The greeting service definition.
</span><span style="color:#75715e"></span>service Greeter {
<span style="color:#75715e">// Sends a greeting
</span><span style="color:#75715e"></span> rpc SayHello (HelloRequest) returns (HelloReply) {}
<span style="color:#75715e">// Sends another greeting
</span><span style="color:#75715e"></span> rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}
}
<span style="color:#75715e">// The request message containing the user&#39;s name.
</span><span style="color:#75715e"></span>message HelloRequest {
string name <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;
}
<span style="color:#75715e">// The response message containing the greetings
</span><span style="color:#75715e"></span>message HelloReply {
string message <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;
}</code></pre></div>
<p>(Don&rsquo;t forget to save the file!)</p>
<h3 id="update-the-client-and-server">Update the client and server</h3>
<p>We now have a new gRPC service definition, but we still need to implement and
call the new method in the human-written parts of our example application.</p>
<h4 id="update-the-server">Update the server</h4>
<p>As you remember, gRPC doesn&rsquo;t provide a server API for Objective-C. Instead, we
need to update the C++ sample server. Open
<code>examples/cpp/helloworld/greeter_server.cc</code>. Implement the new method like this:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-c++" data-lang="c++"><span style="color:#66d9ef">class</span><span style="color:#960050;background-color:#1e0010"> </span><span style="color:#a6e22e">GreeterServiceImpl</span> <span style="color:#66d9ef">final</span> <span style="color:#f92672">:</span> <span style="color:#66d9ef">public</span> Greeter<span style="color:#f92672">::</span>Service {
Status SayHello(ServerContext<span style="color:#f92672">*</span> context, <span style="color:#66d9ef">const</span> HelloRequest<span style="color:#f92672">*</span> request,
HelloReply<span style="color:#f92672">*</span> reply) <span style="color:#66d9ef">override</span> {
std<span style="color:#f92672">::</span>string prefix(<span style="color:#e6db74">&#34;Hello &#34;</span>);
reply<span style="color:#f92672">-&gt;</span>set_message(prefix <span style="color:#f92672">+</span> request<span style="color:#f92672">-&gt;</span>name());
<span style="color:#66d9ef">return</span> Status<span style="color:#f92672">::</span>OK;
}
Status SayHelloAgain(ServerContext<span style="color:#f92672">*</span> context, <span style="color:#66d9ef">const</span> HelloRequest<span style="color:#f92672">*</span> request,
HelloReply<span style="color:#f92672">*</span> reply) <span style="color:#66d9ef">override</span> {
std<span style="color:#f92672">::</span>string prefix(<span style="color:#e6db74">&#34;Hello again &#34;</span>);
reply<span style="color:#f92672">-&gt;</span>set_message(prefix <span style="color:#f92672">+</span> request<span style="color:#f92672">-&gt;</span>name());
<span style="color:#66d9ef">return</span> Status<span style="color:#f92672">::</span>OK;
}
};
</code></pre></div>
<h4 id="update-the-client">Update the client</h4>
<p>Edit <code>examples/objective-c/helloworld/main.m</code> to call the new method like this:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-c" data-lang="c"><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>(<span style="color:#66d9ef">int</span> argc, <span style="color:#66d9ef">char</span> <span style="color:#f92672">*</span> argv[]) {
<span style="color:#960050;background-color:#1e0010">@</span>autoreleasepool {
[GRPCCall useInsecureConnectionsForHost:kHostAddress];
[GRPCCall setUserAgentPrefix:<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#e6db74">&#34;HelloWorld/1.0&#34;</span> forHost:kHostAddress];
HLWGreeter <span style="color:#f92672">*</span>client <span style="color:#f92672">=</span> [[HLWGreeter alloc] initWithHost:kHostAddress];
HLWHelloRequest <span style="color:#f92672">*</span>request <span style="color:#f92672">=</span> [HLWHelloRequest message];
request.name <span style="color:#f92672">=</span> <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#e6db74">&#34;Objective-C&#34;</span>;
[client sayHelloWithRequest:request handler:<span style="color:#f92672">^</span>(HLWHelloReply <span style="color:#f92672">*</span>response, NSError <span style="color:#f92672">*</span>error) {
NSLog(<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#e6db74">&#34;%@&#34;</span>, response.message);
}];
[client sayHelloAgainWithRequest:request handler:<span style="color:#f92672">^</span>(HLWHelloReply <span style="color:#f92672">*</span>response, NSError <span style="color:#f92672">*</span>error) {
NSLog(<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#e6db74">&#34;%@&#34;</span>, response.message);
}];
<span style="color:#66d9ef">return</span> UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}</code></pre></div>
<h3 id="build-and-run">Build and run</h3>
<p>First terminate the server process already running in the background:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">$ pkill greeter_server</code></pre></div>
<p>Then in directory <code>examples/cpp/helloworld</code>, build and run the updated server
with the following commands:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">$ make
$ ./greeter_server &amp;</code></pre></div>
<p>Change directory to <code>examples/objective-c/helloworld</code>, then clean up and
reinstall Pods for the client app with the following commands:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">$ rm -Rf Pods
$ rm Podfile.lock
$ rm -Rf HelloWorld.xcworkspace
$ pod install</code></pre></div>
<p>This regenerates files in <code>Pods/HelloWorld</code> based on the new proto file we wrote
above. Open the client Xcode project in Xcode:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">$ open HelloWorld.xcworkspace</code></pre></div>
<p>and run the client app. If you look at the console messages, you should see two RPC calls,
one to SayHello and one to SayHelloAgain.</p>
<h3 id="troubleshooting">Troubleshooting</h3>
<p><strong>When installing CocoaPods, error prompt <code>activesupport requires Ruby version &gt;= 2.2.2.</code></strong></p>
<p>Install an older version of <code>activesupport</code>, then install CocoaPods:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh"><span style="color:#f92672">[</span>sudo<span style="color:#f92672">]</span> gem install activesupport -v <span style="color:#ae81ff">4</span>.2.6
<span style="color:#f92672">[</span>sudo<span style="color:#f92672">]</span> gem install cocoapods</code></pre></div>
<p><strong>When installing dependencies with CocoaPods, error prompt <code>Unable to find a specification for !ProtoCompiler-gRPCPlugin</code></strong></p>
<p>Update the local clone of spec repo by running <code>pod repo update</code></p>
<p><strong>Compiler error when compiling <code>objective_c_plugin.cc</code></strong></p>
<p>Removing <code>protobuf</code> package with Homebrew before building gRPC may solve
this problem. We are working on a more elegant fix.</p>
<p><strong>When building HellowWorld, error prompt <code>ld: unknown option: --no-as-needed</code></strong></p>
<p>This problem is due to linker <code>ld</code> in Apple LLVM not supporting the
&ndash;no-as-needed option. We are working on a fix right now and will merge the fix
very soon.</p>
<p><strong>When building grpc, error prompt <code>cannot find install-sh install.sh or shtool</code></strong></p>
<p>Remove the gRPC directory, clone a new one and try again. It is likely that some
auto generated files are corrupt; remove and rebuild may solve the problem.</p>
<p><strong>When building grpc, error prompt <code>Can't exec &quot;aclocal&quot;</code></strong></p>
<p>The package <code>automake</code> is missing. Install <code>automake</code> should solve this problem.</p>
<p><strong>When building grpc, error prompt <code>possibly undefined macro: AC_PROG_LIBTOOL</code></strong></p>
<p>The package <code>libtool</code> is missing. Install <code>libtool</code> should solve this problem.</p>
<p><strong>When building grpc, error prompt <code>cannot find install-sh, install.sh, or shtool</code></strong></p>
<p>Some of the auto generated files are corrupt. Remove the entire gRPC directory,
clone from GitHub, and build again.</p>
<p><strong>Cannot find <code>protoc</code> when building HelloWorld</strong></p>
<p>Run <code>brew install protobuf</code> to get <code>protoc</code> compiler.</p>
<h3 id="what-s-next">What&rsquo;s next</h3>
<ul>
<li>Read a full explanation of how gRPC works in <a href="/docs/guides/">What is gRPC?</a>
and <a href="/docs/guides/concepts/">gRPC Concepts</a></li>
<li>Work through a more detailed tutorial in <a href="/docs/tutorials/basic/objective-c/">gRPC Basics: Objective-C</a></li>
<li>Explore the Objective-C core API in its <a href="http://cocoadocs.org/docsets/gRPC/">reference
documentation</a></li>
</ul>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
</body>
</html>