Objective-C Quick Start
This guide gets you started with gRPC on the iOS platform in Objective-C with a simple working example.
Before you begin
System requirements
- macOS version 10.11 (El Capitan) or higher
- iOS version 7.0 or higher
Prerequisites
- CocoaPods version 1.0 or higher
Check the status and version of CocoaPods on your system:
$ pod --version
If CocoaPods is not installed, follow theCocoaPods installinstructions.
- Xcode version 7.2 or higher
Check your Xcode version by running Xcode from Lauchpad, then selectXcode > About Xcode in the menu.
Make sure the command line developer tools are installed:
$ xcode-select --install
autoconf
,automake
,libtool
,pkg-config
$ brew install autoconf automake libtool pkg-config
Download the example
You’ll need a local copy of the sample app source code to work through thisQuickstart. Copy the source code from GitHubrepository:
$ git clone --recursive -b v1.28.1 https://github.com/grpc/grpc.git
Install gRPC plugins and libraries
$ cd grpc
$ make
$ [sudo] make install
Install protoc compiler
$ brew tap grpc/grpc
$ brew install protobuf
Run the server:
For this sample app, we need a gRPC server running on the local machine. gRPCObjective-C API supports creating gRPC clients but not gRPC servers. Thereforeinstead we build and run the C++ server in the same repository:
$ cd examples/cpp/helloworld
$ make
$ ./greeter_server &
Run the client:
Generate client libraries and dependencies
Have CocoaPods generate and install the client library from our .proto files, aswell as installing several dependencies:
$ cd ../../objective-c/helloworld
$ pod install
(This might have to compile OpenSSL, which takes around 15 minutes if Cocoapodsdoesn’t have it yet on your computer’s cache.)
Run the client app
Open the Xcode workspace created by CocoaPods:
$ open HelloWorld.xcworkspace
This will open the app project with Xcode. Run the app in an iOS simulatorby pressing the Run button on the top left corner of Xcode window. You can checkthe calling code in main.m
and see the results in Xcode’s console.
The code sends a HLWHelloRequest
containing the string “Objective-C” to alocal server. The server responds with a HLWHelloResponse
, which contains astring “Hello Objective-C” that is then output to the console.
Congratulations! You’ve just run a client-server application with gRPC.
Update a gRPC service
Now let’s look at how to update the application with an extra method on theserver for the client to call. Our gRPC service is defined using ProtocolBuffers; you can find out lots more about how to define a service in a .proto
file in Protocol Bufferswebsite. For now all youneed to know is that both the server and the client “stub” have a SayHello
RPC method that takes a HelloRequest
parameter from the client and returns aHelloResponse
from the server, and that this method is defined like this:
// 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;
}
Let’s update this so that the Greeter
service has two methods. Editexamples/protos/helloworld.proto
and update it with a new SayHelloAgain
method, with the same request and response types:
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
// Sends another greeting
rpc SayHelloAgain (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;
}
Remember to save the file!
Update the client and server
We now have a new gRPC service definition, but we still need to implement andcall the new method in the human-written parts of our example application.
Update the server
As you remember, gRPC doesn’t provide a server API for Objective-C. Instead, weneed to update the C++ sample server. Openexamples/cpp/helloworld/greeter_server.cc
. Implement the new method like this:
class GreeterServiceImpl final : public Greeter::Service {
Status SayHello(ServerContext* context, const HelloRequest* request,
HelloReply* reply) override {
std::string prefix("Hello ");
reply->set_message(prefix + request->name());
return Status::OK;
}
Status SayHelloAgain(ServerContext* context, const HelloRequest* request,
HelloReply* reply) override {
std::string prefix("Hello again ");
reply->set_message(prefix + request->name());
return Status::OK;
}
};
Update the client
Edit the main function in examples/objective-c/helloworld/main.m
to call the new method like this:
int main(int argc, char * argv[]) {
@autoreleasepool {
HLWGreeter *client = [[HLWGreeter alloc] initWithHost:kHostAddress];
HLWHelloRequest *request = [HLWHelloRequest message];
request.name = @"Objective-C";
GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init];
// this example does not use TLS (secure channel); use insecure channel instead
options.transport = GRPCDefaultTransportImplList.core_insecure;
options.userAgentPrefix = @"HelloWorld/1.0";
[[client sayHelloWithMessage:request
responseHandler:[[HLWResponseHandler alloc] init]
callOptions:options] start];
[[client sayHelloAgainWithMessage:request
responseHandler:[[HLWResponseHandler alloc] init]
callOptions:options] start];
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
Build and run
First terminate the server process already running in the background:
$ pkill greeter_server
Then in directory examples/cpp/helloworld
, build and run the updated serverwith the following commands:
$ make
$ ./greeter_server &
Change directory to examples/objective-c/helloworld
, then clean up andreinstall Pods for the client app with the following commands:
$ rm -Rf Pods
$ rm Podfile.lock
$ rm -Rf HelloWorld.xcworkspace
$ pod install
This regenerates files in Pods/HelloWorld
based on the new proto file we wroteabove. Open the client Xcode project in Xcode:
$ open HelloWorld.xcworkspace
and run the client app. If you look at the console messages, You’ll see two RPC calls,one to SayHello and one to SayHelloAgain.
Troubleshooting
- When installing CocoaPods, error
activesupport requires Ruby version >= 2.2.2
- Install an older version of
activesupport
, then install CocoaPods:
$ [sudo] gem install activesupport -v 4.2.6
$ [sudo] gem install cocoapods
- When installing dependencies with CocoaPods, error
Unable to find a specification for !ProtoCompiler-gRPCPlugin
Update the local clone of spec repo by running
pod repo update
Compiler error when compiling
objective_c_plugin.cc
Removing
protobuf
package with Homebrew before building gRPC may solve thisproblem. We are working on a more elegant fix.When building HellowWorld, error
ld: unknown option: —no-as-needed
This problem is due to linker
ld
in Apple LLVM not supporting the—no-as-needed
option. We are working on a fix right now and will merge thefix very soon.When building grpc, error
cannot find install-sh install.sh or shtool
Remove the gRPC directory, clone a new one and try again. It is likely thatsome auto generated files are corrupt; remove and rebuild may solve theproblem.
When building grpc, error
Can't exec "aclocal"
The package
automake
is missing. Installautomake
should solve this problem.When building grpc, error
possibly undefined macro: AC_PROG_LIBTOOL
The package
libtool
is missing. Installlibtool
should solve this problem.When building grpc, error
cannot find install-sh, install.sh, or shtool
Some of the auto generated files are corrupt. Remove the entire gRPCdirectory, clone from GitHub, and build again.
Cannot find
protoc
when building HelloWorld- Run
brew install protobuf
to get theprotoc
compiler.
What’s next
- Read a full explanation of how gRPC works inWhat is gRPC?andgRPC Concepts.
- Work through a more detailed tutorial ingRPC Basics: Objective-C.
- Explore the Objective-C core API in itsreferencedocumentation.