diff options
Diffstat (limited to 'examples')
-rw-r--r-- | examples/README.md | 2 | ||||
-rw-r--r-- | examples/node/greeter_client.js | 2 | ||||
-rw-r--r-- | examples/objective-c/auth_sample/AuthTestService.podspec | 10 | ||||
-rw-r--r-- | examples/objective-c/auth_sample/MakeRPCViewController.m | 9 | ||||
-rw-r--r-- | examples/objective-c/auth_sample/Podfile | 3 | ||||
-rw-r--r-- | examples/objective-c/auth_sample/README.md | 188 | ||||
-rw-r--r-- | examples/objective-c/helloworld/README.md | 6 | ||||
-rw-r--r-- | examples/objective-c/route_guide/Podfile | 2 | ||||
-rw-r--r-- | examples/objective-c/route_guide/README.md | 358 | ||||
-rw-r--r-- | examples/objective-c/route_guide/RouteGuide.podspec | 10 | ||||
-rw-r--r-- | examples/objective-c/route_guide/RouteGuideClient.xcodeproj/project.pbxproj | 16 | ||||
-rw-r--r-- | examples/objective-c/route_guide/ViewControllers.m | 63 |
12 files changed, 79 insertions, 590 deletions
diff --git a/examples/README.md b/examples/README.md index cc4b239f8e..84ec80057e 100644 --- a/examples/README.md +++ b/examples/README.md @@ -18,7 +18,7 @@ You can find quick start guides for each language, including installation instru * [Android Java](https://github.com/grpc/grpc-java/tree/master/examples/android) * [Python](python/helloworld) * [C#](csharp) -* [Objective-C](objective-c/route_guide) +* [Objective-C](objective-c/helloworld) * [PHP](php) ## What's in this repository? diff --git a/examples/node/greeter_client.js b/examples/node/greeter_client.js index 175f8e6b5a..e0b89bd376 100644 --- a/examples/node/greeter_client.js +++ b/examples/node/greeter_client.js @@ -38,7 +38,7 @@ var hello_proto = grpc.load(PROTO_PATH).helloworld; function main() { var client = new hello_proto.Greeter('localhost:50051', - grpc.Credentials.createInsecure()); + grpc.credentials.createInsecure()); var user; if (process.argv.length >= 3) { user = process.argv[2]; diff --git a/examples/objective-c/auth_sample/AuthTestService.podspec b/examples/objective-c/auth_sample/AuthTestService.podspec index 9f2a2cc361..9521d4971a 100644 --- a/examples/objective-c/auth_sample/AuthTestService.podspec +++ b/examples/objective-c/auth_sample/AuthTestService.podspec @@ -3,13 +3,13 @@ Pod::Spec.new do |s| s.version = "0.0.1" s.license = "New BSD" - s.ios.deployment_target = "6.0" - s.osx.deployment_target = "10.8" + s.ios.deployment_target = "7.1" + s.osx.deployment_target = "10.9" # Base directory where the .proto files are. src = "../../protos" - # Directory where the generated files will be place. + # Directory where the generated files will be placed. dir = "Pods/" + s.name # Run protoc with the Objective-C and gRPC plugins to generate protocol messages and gRPC clients. @@ -22,14 +22,14 @@ Pod::Spec.new do |s| ms.source_files = "#{dir}/*.pbobjc.{h,m}", "#{dir}/**/*.pbobjc.{h,m}" ms.header_mappings_dir = dir ms.requires_arc = false - ms.dependency "Protobuf", "~> 3.0.0-alpha-3" + ms.dependency "Protobuf", "~> 3.0.0-alpha-4" end s.subspec "Services" do |ss| ss.source_files = "#{dir}/*.pbrpc.{h,m}", "#{dir}/**/*.pbrpc.{h,m}" ss.header_mappings_dir = dir ss.requires_arc = true - ss.dependency "gRPC", "~> 0.6" + ss.dependency "gRPC", "~> 0.11" ss.dependency "#{s.name}/Messages" end end diff --git a/examples/objective-c/auth_sample/MakeRPCViewController.m b/examples/objective-c/auth_sample/MakeRPCViewController.m index 366bc9deea..4fd23dc144 100644 --- a/examples/objective-c/auth_sample/MakeRPCViewController.m +++ b/examples/objective-c/auth_sample/MakeRPCViewController.m @@ -35,7 +35,6 @@ #import <AuthTestService/AuthSample.pbrpc.h> #import <Google/SignIn.h> -#include <grpc/status.h> #import <ProtoRPC/ProtoRPC.h> NSString * const kTestScope = @"https://www.googleapis.com/auth/xapi.zoo"; @@ -49,10 +48,10 @@ static NSString * const kTestHostAddress = @"grpc-test.sandbox.google.com"; @implementation NSError (AuthSample) - (NSString *)UIDescription { - if (self.code == GRPC_STATUS_UNAUTHENTICATED) { + if (self.code == GRPCErrorCodeUnauthenticated) { // Authentication error. OAuth2 specifies we'll receive a challenge header. - // |userInfo[kGRPCStatusMetadataKey]| is the dictionary of response metadata. - NSString *challengeHeader = self.userInfo[kGRPCStatusMetadataKey][@"www-authenticate"] ?: @""; + // |userInfo[kGRPCHeadersKey]| is the dictionary of response headers. + NSString *challengeHeader = self.userInfo[kGRPCHeadersKey][@"www-authenticate"] ?: @""; return [@"Invalid credentials. Server challenge:\n" stringByAppendingString:challengeHeader]; } else { // Any other error. @@ -89,7 +88,7 @@ static NSString * const kTestHostAddress = @"grpc-test.sandbox.google.com"; // Set the access token to be used. NSString *accessToken = GIDSignIn.sharedInstance.currentUser.authentication.accessToken; - call.requestMetadata[@"Authorization"] = [@"Bearer " stringByAppendingString:accessToken]; + call.requestHeaders[@"Authorization"] = [@"Bearer " stringByAppendingString:accessToken]; // Start the RPC. [call start]; diff --git a/examples/objective-c/auth_sample/Podfile b/examples/objective-c/auth_sample/Podfile index dd4fd558c0..ea70511dc6 100644 --- a/examples/objective-c/auth_sample/Podfile +++ b/examples/objective-c/auth_sample/Podfile @@ -1,6 +1,9 @@ source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' +pod 'Protobuf', :path => "../../../third_party/protobuf" +pod 'gRPC', :path => "../../.." + target 'AuthSample' do # Depend on the generated AuthTestService library. pod 'AuthTestService', :path => '.' diff --git a/examples/objective-c/auth_sample/README.md b/examples/objective-c/auth_sample/README.md index 5ae6452619..c560b7af65 100644 --- a/examples/objective-c/auth_sample/README.md +++ b/examples/objective-c/auth_sample/README.md @@ -1,189 +1,3 @@ #OAuth2 on gRPC: Objective-C -This example application demostrates how to use OAuth2 on gRPC to make authenticated API calls on -behalf of a user. By walking through it you'll learn how to use the Objective-C gRPC API to: - -- Initialize and configure a remote call object before the RPC is started. -- Set request metadata elements on a call, which are semantically equivalent to HTTP request -headers. -- Read response metadata from a call, which is equivalent to HTTP response headers and trailers. - -It assumes you know the basics on how to make gRPC API calls using the Objective-C client library, -as shown in the [Hello World](../helloworld) -or [Route Guide](../route_guide) tutorials, -and are familiar with OAuth2 concepts like _access token_. - -- [Example code and setup](#setup) -- [Try it out!](#try) -- [Create an RPC object and start it later](#rpc-object) -- [Set request metadata of a call: Authorization header with an access token](#request-metadata) -- [Get response metadata of a call: Auth challenge header](#response-metadata) - -<a name="setup"></a> -## Example code and setup - -The example code for our tutorial is in [examples/objective-c/auth_sample](.). -To download the example, clone this repository by running the following command: -```shell -$ git clone https://github.com/grpc/grpc.git -``` - -Then change your current directory to `examples/objective-c/auth_sample`: -```shell -$ cd examples/objective-c/auth_sample -``` - -Our example is a simple application with two views. The first one lets a user sign in and out using -the OAuth2 flow of Google's [iOS SignIn library](https://developers.google.com/identity/sign-in/ios/). -(Google's library is used in this example because the test gRPC service we are going to call expects -Google account credentials, but neither gRPC nor the Objective-C client library is tied to any -specific OAuth2 provider). The second view makes a gRPC request to the test server, using the -access token obtained by the first view. - -Note: OAuth2 libraries need the application to register and obtain an ID from the identity provider -(in the case of this example app, Google). The app's XCode project is configured using that ID, so -you shouldn't copy this project "as is" for your own app: it would result in your app being -identified in the consent screen as "gRPC-AuthSample", and not having access to real Google -services. Instead, configure your own XCode project following the [instructions here](https://developers.google.com/identity/sign-in/ios/). - -As with the other examples, you also should have [Cocoapods](https://cocoapods.org/#install) -installed, as well as the relevant tools to generate the client library code. You can obtain the -latter by following [these setup instructions](https://github.com/grpc/homebrew-grpc). - - -<a name="try"></a> -## Try it out! - -To try the sample app, first have Cocoapods generate and install the client library for our .proto -files: - -```shell -$ pod install -``` - -(This might have to compile OpenSSL, which takes around 15 minutes if Cocoapods doesn't have it yet -on your computer's cache). - -Finally, open the XCode workspace created by Cocoapods, and run the app. - -The first view, `SelectUserViewController.h/m`, asks you to sign in with your Google account, and to -give the "gRPC-AuthSample" app the following permissions: - -- View your email address. -- View your basic profile info. -- "Test scope for access to the Zoo service". - -This last permission, corresponding to the scope `https://www.googleapis.com/auth/xapi.zoo` doesn't -grant any real capability: it's only used for testing. You can log out at any time. - -The second view, `MakeRPCViewController.h/m`, makes a gRPC request to a test server at -https://grpc-test.sandbox.google.com, sending the access token along with the request. The test -service simply validates the token and writes in its response which user it belongs to, and which -scopes it gives access to. (The client application already knows those two values; it's a way to -verify that everything went as expected). - -The next sections guide you step-by-step through how the gRPC call in `MakeRPCViewController` is -performed. - -<a name="rpc-object"></a> -## Create an RPC object and start it later - -The other basic tutorials show how to invoke an RPC by calling an asynchronous method in a generated -client object. This shows how to initialize an object that represents the RPC, and configure it -before starting the network request. - -Assume you have a proto service definition like this: - -```protobuf -option objc_class_prefix = "AUTH"; - -service TestService { - rpc UnaryCall(Request) returns (Response); -} -``` - -A `unaryCallWithRequest:handler:` method, with which you're already familiar, is generated for the -`AUTHTestService` class: - -```objective-c -[client unaryCallWithRequest:request handler:^(AUTHResponse *response, NSError *error) { - ... -}]; -``` - -In addition, an `RPCToUnaryCallWithRequest:handler:` method is generated, which returns a -not-yet-started RPC object: - -```objective-c -#import <ProtoRPC/ProtoRPC.h> - -ProtoRPC *call = - [client RPCToUnaryCallWithRequest:request handler:^(AUTHResponse *response, NSError *error) { - ... - }]; -``` - -The RPC represented by this object can be started at any later time like this: - -```objective-c -[call start]; -``` - -<a name="request-metadata"></a> -## Set request metadata of a call: Authorization header with an access token - -The `ProtoRPC` class has a `requestMetadata` property (inherited from `GRPCCall`) defined like this: - -```objective-c -- (NSMutableDictionary *)requestMetadata; // nonatomic -- (void)setRequestMetadata:(NSDictionary *)requestMetadata; // nonatomic, copy -``` - -Setting it to a dictionary of metadata keys and values will have them sent on the wire when the call -is started. gRPC metadata are pieces of information about the call sent by the client to the server -(and vice versa). They take the form of key-value pairs and are essentially opaque to gRPC itself. - -```objective-c -call.requestMetadata = @{@"My-Header": @"Value for this header", - @"Another-Header": @"Its value"}; -``` - -For convenience, the property is initialized with an empty `NSMutableDictionary`, so that request -metadata elements can be set like this: - -```objective-c -call.requestMetadata[@"My-Header"] = @"Value for this header"; -``` - -If you have an access token, OAuth2 specifies it is to be sent in this format: - -```objective-c -call.requestMetadata[@"Authorization"] = [@"Bearer " stringByAppendingString:accessToken]; -``` - -<a name="response-metadata"></a> -## Get response metadata of a call: Auth challenge header - -The `ProtoRPC` class also inherits a `responseMetadata` property, analogous to the request metadata -we just looked at. It's defined like this: - -```objective-c -@property(atomic, readonly) NSDictionary *responseMetadata; -``` - -To access OAuth2's authentication challenge header you write: - -```objective-c -call.responseMetadata[@"www-authenticate"] -``` - -Note that, as gRPC metadata elements are mapped to HTTP/2 headers (or trailers), the keys of the -response metadata are always ASCII strings in lowercase. - -Many uses cases of response metadata are getting more details about an RPC error. For convenience, -when a `NSError` instance is passed to an RPC handler block, the response metadata dictionary can -also be accessed this way: - -```objective-c -error.userInfo[kGRPCStatusMetadataKey] -``` +This is the supporting code for the tutorial "[OAuth2 on gRPC: Objective-C](http://www.grpc.io/docs/tutorials/auth/oauth2-objective-c.html)." diff --git a/examples/objective-c/helloworld/README.md b/examples/objective-c/helloworld/README.md index 75df1a7a26..81c5aaa7bc 100644 --- a/examples/objective-c/helloworld/README.md +++ b/examples/objective-c/helloworld/README.md @@ -12,11 +12,13 @@ Here's how to build and run the Objective-C implementation of the [Hello World]( example used in [Getting started](https://github.com/grpc/grpc/tree/master/examples). The example code for this and our other examples lives in the `examples` directory. Clone -this repository to your local machine by running the following command: +this repository to your local machine by running the following commands: ```sh $ git clone https://github.com/grpc/grpc.git +$ cd grpc +$ git submodule update --init ``` Change your current directory to `examples/objective-c/helloworld` @@ -53,4 +55,4 @@ responds with a `HLWHelloResponse`, which contains a string that is then output ## Tutorial -You can find a more detailed tutorial in [gRPC Basics: Objective-C](../route_guide/README.md). +You can find a more detailed tutorial in [gRPC Basics: Objective-C](http://www.grpc.io/docs/tutorials/basic/objective-c.html). diff --git a/examples/objective-c/route_guide/Podfile b/examples/objective-c/route_guide/Podfile index a97f414685..efa46bba4f 100644 --- a/examples/objective-c/route_guide/Podfile +++ b/examples/objective-c/route_guide/Podfile @@ -2,6 +2,8 @@ source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' target 'RouteGuideClient' do + pod 'Protobuf', :path => "../../../third_party/protobuf" + pod 'gRPC', :path => "../../.." # Depend on the generated RouteGuide library. pod 'RouteGuide', :path => '.' end diff --git a/examples/objective-c/route_guide/README.md b/examples/objective-c/route_guide/README.md index 15864c01f4..6a6f7c0d33 100644 --- a/examples/objective-c/route_guide/README.md +++ b/examples/objective-c/route_guide/README.md @@ -1,360 +1,4 @@ #gRPC Basics: Objective-C -This tutorial provides a basic Objective-C programmer's introduction to working with gRPC. By -walking through this example you'll learn how to: +This is the supporting code for the tutorial "[gRPC Basics: Objective-C](http://www.grpc.io/docs/tutorials/basic/objective-c.html)." -- Define a service in a .proto file. -- Generate client code using the protocol buffer compiler. -- Use the Objective-C gRPC API to write a simple client for your service. - -It assumes a passing familiarity with [protocol buffers](https://developers.google.com/protocol-buffers/docs/overview). -Note that the example in this tutorial uses the proto3 version of the protocol buffers language, -which is currently in alpha release: you can find out more in the [proto3 language guide](https://developers.google.com/protocol-buffers/docs/proto3) -and see the [release notes](https://github.com/google/protobuf/releases) for the new version in the -protocol buffers Github repository. - -This isn't a comprehensive guide to using gRPC in Objective-C: more reference documentation is -coming soon. - -- [Why use gRPC?](#why-grpc) -- [Example code and setup](#setup) -- [Try it out!](#try) -- [Defining the service](#proto) -- [Generating client code](#protoc) -- [Creating the client](#client) - -<a name="why-grpc"></a> -## Why use gRPC? - -With gRPC you can define your service once in a .proto file and implement clients and servers in any -of gRPC's supported languages, which in turn can be run in environments ranging from servers inside -Google to your own tablet - all the complexity of communication between different languages and -environments is handled for you by gRPC. You also get all the advantages of working with protocol -buffers, including efficient serialization, a simple IDL, and easy interface updating. - -gRPC and proto3 are specially suited for mobile clients: gRPC is implemented on top of HTTP/2, which -results in network bandwidth savings over using HTTP/1.1. Serialization and parsing of the proto -binary format is more efficient than the equivalent JSON, resulting in CPU and battery savings. And -proto3 uses a runtime that has been optimized over the years at Google to keep code size to a -minimum. The latter is important in Objective-C, because the ability of the compiler to strip unused -code is limited by the dynamic nature of the language. - - -<a name="setup"></a> -## Example code and setup - -The example code for our tutorial is in [examples/objective-c/route_guide](.). -To download the example, clone this repository by running the following command: -```shell -$ git clone https://github.com/grpc/grpc.git -``` - -Then change your current directory to `examples/objective-c/route_guide`: -```shell -$ cd examples/objective-c/route_guide -``` - -Our example is a simple route mapping application that lets clients get information about features -on their route, create a summary of their route, and exchange route information such as traffic -updates with the server and other clients. - -You also should have [Cocoapods](https://cocoapods.org/#install) installed, as well as the relevant -tools to generate the client library code (and a server in another language, for testing). You can -obtain the latter by following [these setup instructions](https://github.com/grpc/homebrew-grpc). - - -<a name="try"></a> -## Try it out! - -To try the sample app, we need a gRPC server running locally. Let's compile and run, for example, -the C++ server in this repository: - -```shell -$ pushd ../../cpp/route_guide -$ make -$ ./route_guide_server & -$ popd -``` - -Now have Cocoapods generate and install the client library for our .proto files: - -```shell -$ pod install -``` - -(This might have to compile OpenSSL, which takes around 15 minutes if Cocoapods doesn't have it yet -on your computer's cache). - -Finally, open the XCode workspace created by Cocoapods, and run the app. You can check the calling -code in `ViewControllers.m` and see the results in XCode's log console. - -The next sections guide you step-by-step through how this proto service is defined, how to generate -a client library from it, and how to create an app that uses that library. - - -<a name="proto"></a> -## Defining the service - -First let's look at how the service we're using is defined. A gRPC *service* and its method -*request* and *response* types using [protocol buffers](https://developers.google.com/protocol-buffers/docs/overview). -You can see the complete .proto file for our example in [`examples/protos/route_guide.proto`](../../protos/route_guide.proto). - -To define a service, you specify a named `service` in your .proto file: - -```protobuf -service RouteGuide { - ... -} -``` - -Then you define `rpc` methods inside your service definition, specifying their request and response -types. Protocol buffers let you define four kinds of service method, all of which are used in the -`RouteGuide` service: - -- A *simple RPC* where the client sends a request to the server and receives a response later, just -like a normal remote procedure call. -```protobuf - // Obtains the feature at a given position. - rpc GetFeature(Point) returns (Feature) {} -``` - -- A *response-streaming RPC* where the client sends a request to the server and gets back a stream -of response messages. You specify a response-streaming method by placing the `stream` keyword before -the *response* type. -```protobuf - // Obtains the Features available within the given Rectangle. Results are - // streamed rather than returned at once (e.g. in a response message with a - // repeated field), as the rectangle may cover a large area and contain a - // huge number of features. - rpc ListFeatures(Rectangle) returns (stream Feature) {} -``` - -- A *request-streaming RPC* where the client sends a sequence of messages to the server. Once the -client has finished writing the messages, it waits for the server to read them all and return its -response. You specify a request-streaming method by placing the `stream` keyword before the -*request* type. -```protobuf - // Accepts a stream of Points on a route being traversed, returning a - // RouteSummary when traversal is completed. - rpc RecordRoute(stream Point) returns (RouteSummary) {} -``` - -- A *bidirectional streaming RPC* where both sides send a sequence of messages to the other. The two -streams operate independently, so clients and servers can read and write in whatever order they -like: for example, the server could wait to receive all the client messages before writing its -responses, or it could alternately read a message then write a message, or some other combination of -reads and writes. The order of messages in each stream is preserved. You specify this type of method -by placing the `stream` keyword before both the request and the response. -```protobuf - // Accepts a stream of RouteNotes sent while a route is being traversed, - // while receiving other RouteNotes (e.g. from other users). - rpc RouteChat(stream RouteNote) returns (stream RouteNote) {} -``` - -Our .proto file also contains protocol buffer message type definitions for all the request and -response types used in our service methods - for example, here's the `Point` message type: -```protobuf -// Points are represented as latitude-longitude pairs in the E7 representation -// (degrees multiplied by 10**7 and rounded to the nearest integer). -// Latitudes should be in the range +/- 90 degrees and longitude should be in -// the range +/- 180 degrees (inclusive). -message Point { - int32 latitude = 1; - int32 longitude = 2; -} -``` - -You can specify a prefix to be used for your generated classes by adding the `objc_class_prefix` -option at the top of the file. For example: -```protobuf -option objc_class_prefix = "RTG"; -``` - - -<a name="protoc"></a> -## Generating client code - -Next we need to generate the gRPC client interfaces from our .proto service definition. We do this -using the protocol buffer compiler (`protoc`) with a special gRPC Objective-C plugin. - -For simplicity, we've provided a [Podspec file](RouteGuide.podspec) -that runs `protoc` for you with the appropriate plugin, input, and output, and describes how to -compile the generated files. You just need to run in this directory (`examples/objective-c/route_guide`): - -```shell -$ pod install -``` - -which, before installing the generated library in the XCode project of this sample, runs: - -```shell -$ protoc -I ../../protos --objc_out=Pods/RouteGuide --objcgrpc_out=Pods/RouteGuide ../../protos/route_guide.proto -``` - -Running this command generates the following files under `Pods/RouteGuide/`: -- `RouteGuide.pbobjc.h`, the header which declares your generated message classes. -- `RouteGuide.pbobjc.m`, which contains the implementation of your message classes. -- `RouteGuide.pbrpc.h`, the header which declares your generated service classes. -- `RouteGuide.pbrpc.m`, which contains the implementation of your service classes. - -These contain: -- All the protocol buffer code to populate, serialize, and retrieve our request and response message -types. -- A class called `RTGRouteGuide` that lets clients call the methods defined in the `RouteGuide` -service. - -You can also use the provided Podspec file to generate client code from any other proto service -definition; just replace the name (matching the file name), version, and other metadata. - - -<a name="client"></a> -## Creating the client - -In this section, we'll look at creating an Objective-C client for our `RouteGuide` service. You can -see our complete example client code in [ViewControllers.m](ViewControllers.m). -(Note: In your apps, for maintainability and readability reasons, you shouldn't put all of your view -controllers in a single file; it's done here only to simplify the learning process). - -### Constructing a client object - -To call service methods, we first need to create a client object, an instance of the generated -`RTGRouteGuide` class. The designated initializer of the class expects a `NSString *` with the -server address and port we want to connect to: - -```objective-c -#import <RouteGuide/RouteGuide.pbrpc.h> - -static NSString * const kHostAddress = @"http://localhost:50051"; - -... - -RTGRouteGuide *client = [[RTGRouteGuide alloc] initWithHost:kHostAddress]; -``` - -Notice that we've specified the HTTP scheme in the host address. This is because the server we will -be using to test our client doesn't use [TLS](http://en.wikipedia.org/wiki/Transport_Layer_Security). -This is fine because it will be running locally on our development machine. The most common case, -though, is connecting with a gRPC server on the internet, running gRPC over TLS. For that case, the -HTTPS scheme can be specified (or no scheme at all, as HTTPS is the default value). The default -value of the port is that of the scheme selected: 443 for HTTPS and 80 for HTTP. - - -### Calling service methods - -Now let's look at how we call our service methods. As you will see, all these methods are -asynchronous, so you can call them from the main thread of your app without worrying about freezing -your UI or the OS killing your app. - -#### Simple RPC - -Calling the simple RPC `GetFeature` is nearly as straightforward as calling any other asynchronous -method on Cocoa. - -```objective-c -RTGPoint *point = [RTGPoint message]; -point.latitude = 40E7; -point.longitude = -74E7; - -[client getFeatureWithRequest:point handler:^(RTGFeature *response, NSError *error) { - if (response) { - // Successful response received - } else { - // RPC error - } -}]; -``` - -As you can see, we create and populate a request protocol buffer object (in our case `RTGPoint`). -Then, we call the method on the client object, passing it the request, and a block to handle the -response (or any RPC error). If the RPC finishes successfully, the handler block is called with a -`nil` error argument, and we can read the response information from the server from the response -argument. If, instead, some RPC error happens, the handler block is called with a `nil` response -argument, and we can read the details of the problem from the error argument. - -```objective-c -NSLog(@"Found feature called %@ at %@.", response.name, response.location); -``` - -#### Streaming RPCs - -Now let's look at our streaming methods. Here's where we call the response-streaming method -`ListFeatures`, which results in our client receiving a stream of geographical `RTGFeature`s: - -```objective-c -[client listFeaturesWithRequest:rectangle - eventHandler:^(BOOL done, RTGFeature *response, NSError *error) { - if (response) { - // Element of the stream of responses received - } else if (error) { - // RPC error; the stream is over. - } - if (done) { - // The stream is over (all the responses were received, or an error occured). Do any cleanup. - } -}]; -``` - -Notice how the signature of the `eventHandler` block now includes a `BOOL done` parameter. The -`eventHandler` block can be called any number of times; only on the last call is the `done` argument -value set to `YES`. If an error occurs, the RPC finishes and the block is called with the arguments -`(YES, nil, error)`. - -The request-streaming method `RecordRoute` expects a stream of `RTGPoint`s from the cient. This -stream is passed to the method as an object of class `GRXWriter`. The simplest way to create one is -to initialize one from a `NSArray` object: - - -```objective-c -#import <RxLibrary/GRXWriter+Immediate.h> - -... - -RTGPoint *point1 = [RTGPoint message]; -point.latitude = 40E7; -point.longitude = -74E7; - -RTGPoint *point2 = [RTGPoint message]; -point.latitude = 40E7; -point.longitude = -74E7; - -GRXWriter *locationsWriter = [GRXWriter writerWithContainer:@[point1, point2]]; - -[client recordRouteWithRequestsWriter:locationsWriter - handler:^(RTGRouteSummary *response, NSError *error) { - if (response) { - NSLog(@"Finished trip with %i points", response.pointCount); - NSLog(@"Passed %i features", response.featureCount); - NSLog(@"Travelled %i meters", response.distance); - NSLog(@"It took %i seconds", response.elapsedTime); - } else { - NSLog(@"RPC error: %@", error); - } -}]; - -``` - -The `GRXWriter` class is generic enough to allow for asynchronous streams, streams of future values, -or even infinite streams. - -Finally, let's look at our bidirectional streaming RPC `RouteChat()`. The way to call a -bidirectional streaming RPC is just a combination of how to call request-streaming RPCs and -response-streaming RPCs. - -```objective-c -[client routeChatWithRequestsWriter:notesWriter - eventHandler:^(BOOL done, RTGRouteNote *note, NSError *error) { - if (note) { - NSLog(@"Got message %@ at %@", note.message, note.location); - } else if (error) { - NSLog(@"RPC error: %@", error); - } - if (done) { - NSLog(@"Chat ended."); - } -}]; -``` - -The semantics for the handler block and the `GRXWriter` argument here are exactly the same as for -our request-streaming and response-streaming methods. Although both client and server will always -get the other's messages in the order they were written, the two streams operate completely -independently. diff --git a/examples/objective-c/route_guide/RouteGuide.podspec b/examples/objective-c/route_guide/RouteGuide.podspec index 7b99a6c6a7..e00f827e3a 100644 --- a/examples/objective-c/route_guide/RouteGuide.podspec +++ b/examples/objective-c/route_guide/RouteGuide.podspec @@ -3,13 +3,13 @@ Pod::Spec.new do |s| s.version = "0.0.1" s.license = "New BSD" - s.ios.deployment_target = "6.0" - s.osx.deployment_target = "10.8" + s.ios.deployment_target = "7.1" + s.osx.deployment_target = "10.9" # Base directory where the .proto files are. src = "../../protos" - # Directory where the generated files will be place. + # Directory where the generated files will be placed. dir = "Pods/" + s.name # Run protoc with the Objective-C and gRPC plugins to generate protocol messages and gRPC clients. @@ -22,14 +22,14 @@ Pod::Spec.new do |s| ms.source_files = "#{dir}/*.pbobjc.{h,m}", "#{dir}/**/*.pbobjc.{h,m}" ms.header_mappings_dir = dir ms.requires_arc = false - ms.dependency "Protobuf", "~> 3.0.0-alpha-3" + ms.dependency "Protobuf", "~> 3.0.0-alpha-4" end s.subspec "Services" do |ss| ss.source_files = "#{dir}/*.pbrpc.{h,m}", "#{dir}/**/*.pbrpc.{h,m}" ss.header_mappings_dir = dir ss.requires_arc = true - ss.dependency "gRPC", "~> 0.6" + ss.dependency "gRPC", "~> 0.11" ss.dependency "#{s.name}/Messages" end end diff --git a/examples/objective-c/route_guide/RouteGuideClient.xcodeproj/project.pbxproj b/examples/objective-c/route_guide/RouteGuideClient.xcodeproj/project.pbxproj index 6ab6b27a1b..f99775562c 100644 --- a/examples/objective-c/route_guide/RouteGuideClient.xcodeproj/project.pbxproj +++ b/examples/objective-c/route_guide/RouteGuideClient.xcodeproj/project.pbxproj @@ -121,6 +121,7 @@ 6325277A1B1D0395003073D9 /* Frameworks */, 6325277B1B1D0395003073D9 /* Resources */, FFE0BCF30339E7A50A989EAB /* Copy Pods Resources */, + B5388EC5A25E89021740B916 /* Embed Pods Frameworks */, ); buildRules = ( ); @@ -177,6 +178,21 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + B5388EC5A25E89021740B916 /* Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-RouteGuideClient/Pods-RouteGuideClient-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; C6FC30AD2376EC04317237C5 /* Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; diff --git a/examples/objective-c/route_guide/ViewControllers.m b/examples/objective-c/route_guide/ViewControllers.m index cfc3338bca..0b1a1cf482 100644 --- a/examples/objective-c/route_guide/ViewControllers.m +++ b/examples/objective-c/route_guide/ViewControllers.m @@ -32,13 +32,14 @@ */ #import <UIKit/UIKit.h> +#import <GRPCClient/GRPCCall+Tests.h> #import <RouteGuide/RouteGuide.pbrpc.h> #import <RxLibrary/GRXWriter+Immediate.h> #import <RxLibrary/GRXWriter+Transformations.h> -static NSString * const kHostAddress = @"http://localhost:50051"; +static NSString * const kHostAddress = @"localhost:50051"; -// Category to override RTGPoint's description. +/** Category to override RTGPoint's description. */ @interface RTGPoint (Description) - (NSString *)description; @end @@ -53,7 +54,7 @@ static NSString * const kHostAddress = @"http://localhost:50051"; } @end -// Category to give RTGRouteNote a convenience constructor. +/** Category to give RTGRouteNote a convenience constructor. */ @interface RTGRouteNote (Constructors) + (instancetype)noteWithMessage:(NSString *)message latitude:(float)latitude @@ -75,9 +76,10 @@ static NSString * const kHostAddress = @"http://localhost:50051"; #pragma mark Demo: Get Feature -// Run the getFeature demo. Calls getFeature with a point known to have a feature and a point known -// not to have a feature. - +/** + * Run the getFeature demo. Calls getFeature with a point known to have a feature and a point known + * not to have a feature. + */ @interface GetFeatureViewController : UIViewController @end @@ -86,7 +88,10 @@ static NSString * const kHostAddress = @"http://localhost:50051"; - (void)viewDidLoad { [super viewDidLoad]; - RTGRouteGuide *client = [[RTGRouteGuide alloc] initWithHost:kHostAddress]; + // This only needs to be done once per host, before creating service objects for that host. + [GRPCCall useInsecureConnectionsForHost:kHostAddress]; + + RTGRouteGuide *service = [[RTGRouteGuide alloc] initWithHost:kHostAddress]; void (^handler)(RTGFeature *response, NSError *error) = ^(RTGFeature *response, NSError *error) { if (response.name.length) { @@ -102,8 +107,8 @@ static NSString * const kHostAddress = @"http://localhost:50051"; point.latitude = 409146138; point.longitude = -746188906; - [client getFeatureWithRequest:point handler:handler]; - [client getFeatureWithRequest:[RTGPoint message] handler:handler]; + [service getFeatureWithRequest:point handler:handler]; + [service getFeatureWithRequest:[RTGPoint message] handler:handler]; } @end @@ -111,9 +116,10 @@ static NSString * const kHostAddress = @"http://localhost:50051"; #pragma mark Demo: List Features -// Run the listFeatures demo. Calls listFeatures with a rectangle containing all of the features in -// the pre-generated database. Prints each response as it comes in. - +/** + * Run the listFeatures demo. Calls listFeatures with a rectangle containing all of the features in + * the pre-generated database. Prints each response as it comes in. + */ @interface ListFeaturesViewController : UIViewController @end @@ -122,7 +128,7 @@ static NSString * const kHostAddress = @"http://localhost:50051"; - (void)viewDidLoad { [super viewDidLoad]; - RTGRouteGuide *client = [[RTGRouteGuide alloc] initWithHost:kHostAddress]; + RTGRouteGuide *service = [[RTGRouteGuide alloc] initWithHost:kHostAddress]; RTGRectangle *rectangle = [RTGRectangle message]; rectangle.lo.latitude = 405E6; @@ -131,8 +137,8 @@ static NSString * const kHostAddress = @"http://localhost:50051"; rectangle.hi.longitude = -745E6; NSLog(@"Looking for features between %@ and %@", rectangle.lo, rectangle.hi); - [client listFeaturesWithRequest:rectangle - eventHandler:^(BOOL done, RTGFeature *response, NSError *error) { + [service listFeaturesWithRequest:rectangle + eventHandler:^(BOOL done, RTGFeature *response, NSError *error) { if (response) { NSLog(@"Found feature at %@ called %@.", response.location, response.name); } else if (error) { @@ -146,10 +152,11 @@ static NSString * const kHostAddress = @"http://localhost:50051"; #pragma mark Demo: Record Route -// Run the recordRoute demo. Sends several randomly chosen points from the pre-generated feature -// database with a variable delay in between. Prints the statistics when they are sent from the -// server. - +/** + * Run the recordRoute demo. Sends several randomly chosen points from the pre-generated feature + * database with a variable delay in between. Prints the statistics when they are sent from the + * server. + */ @interface RecordRouteViewController : UIViewController @end @@ -171,9 +178,10 @@ static NSString * const kHostAddress = @"http://localhost:50051"; return location; }]; - RTGRouteGuide *client = [[RTGRouteGuide alloc] initWithHost:kHostAddress]; + RTGRouteGuide *service = [[RTGRouteGuide alloc] initWithHost:kHostAddress]; - [client recordRouteWithRequestsWriter:locations handler:^(RTGRouteSummary *response, NSError *error) { + [service recordRouteWithRequestsWriter:locations + handler:^(RTGRouteSummary *response, NSError *error) { if (response) { NSLog(@"Finished trip with %i points", response.pointCount); NSLog(@"Passed %i features", response.featureCount); @@ -190,9 +198,10 @@ static NSString * const kHostAddress = @"http://localhost:50051"; #pragma mark Demo: Route Chat -// Run the routeChat demo. Send some chat messages, and print any chat messages that are sent from -// the server. - +/** + * Run the routeChat demo. Send some chat messages, and print any chat messages that are sent from + * the server. + */ @interface RouteChatViewController : UIViewController @end @@ -210,10 +219,10 @@ static NSString * const kHostAddress = @"http://localhost:50051"; return note; }]; - RTGRouteGuide *client = [[RTGRouteGuide alloc] initWithHost:kHostAddress]; + RTGRouteGuide *service = [[RTGRouteGuide alloc] initWithHost:kHostAddress]; - [client routeChatWithRequestsWriter:notesWriter - eventHandler:^(BOOL done, RTGRouteNote *note, NSError *error) { + [service routeChatWithRequestsWriter:notesWriter + eventHandler:^(BOOL done, RTGRouteNote *note, NSError *error) { if (note) { NSLog(@"Got message %@ at %@", note.message, note.location); } else if (error) { |