Update tutorial to v2 API

This commit is contained in:
Muxi Yan 2019-11-27 11:32:13 -08:00
parent 6d3441ec34
commit 034eb670ec
1 changed files with 85 additions and 59 deletions

View File

@ -266,22 +266,23 @@ expects a `NSString *` with the server address and port we want to connect to:
```objective-c ```objective-c
#import <GRPCClient/GRPCCall+Tests.h> #import <GRPCClient/GRPCCall+Tests.h>
#import <RouteGuide/RouteGuide.pbrpc.h> #import <RouteGuide/RouteGuide.pbrpc.h>
#import <GRPCClient/GRPCTransport.h>
static NSString * const kHostAddress = @"localhost:50051"; static NSString * const kHostAddress = @"localhost:50051";
... ...
[GRPCCall useInsecureConnectionsForHost:kHostAddress]; GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init];
options.transport = GRPCDefaultTransportImplList.core_insecure;
RTGRouteGuide *service = [[RTGRouteGuide alloc] initWithHost:kHostAddress]; RTGRouteGuide *service = [[RTGRouteGuide alloc] initWithHost:kHostAddress callOptions:options];
``` ```
Notice that before constructing our service object we've told the gRPC library Notice that we our service is constructed with an insecure transport. This is
to use insecure connections for that host:port pair. This is because the server because the server we will be using to test our client doesn't use
we will be using to test our client doesn't use
[TLS](https://en.wikipedia.org/wiki/Transport_Layer_Security). This is fine [TLS](https://en.wikipedia.org/wiki/Transport_Layer_Security). This is fine
because it will be running locally on our development machine. The most common 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 case, though, is connecting with a gRPC server on the internet, running gRPC
over TLS. For that case, the `useInsecureConnectionsForHost:` call isn't needed, over TLS. For that case, the setting the option `options.transport` isn't
and the port defaults to 443 if absent. needed because gRPC will use a secure TLS transport by default.
#### Calling service methods #### Calling service methods
@ -296,17 +297,23 @@ Calling the simple RPC `GetFeature` is as straightforward as calling any other
asynchronous method on Cocoa. asynchronous method on Cocoa.
```objective-c ```objective-c
RTGPoint *point = [RTGPoint message]; RTGPoint *point = [RTGPoint message];
point.latitude = 40E7; point.latitude = 40E7;
point.longitude = -74E7; point.longitude = -74E7;
[service getFeatureWithRequest:point handler:^(RTGFeature *response, NSError *error) { GRPCUnaryResponseHandler *handler =
if (response) { [[GRPCUnaryResponseHandler alloc] initWithResponseHandler:
// Successful response received ^(RTGFeature *response, NSError *error) {
} else { if (response) {
// RPC error // Successful response received
} } else {
}]; // RPC error
}
}
responseDispatchQueue:nil];
[[service getFeatureWithMessage:point responseHandler:handler callOptions:nil] start];
``` ```
As you can see, we create and populate a request protocol buffer object (in our As you can see, we create and populate a request protocol buffer object (in our
@ -318,10 +325,6 @@ 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 a `nil` response argument, and we can read the details of the problem from the
error argument. error argument.
```objective-c
NSLog(@"Found feature called %@ at %@.", response.name, response.location);
```
##### Streaming RPCs ##### Streaming RPCs
Now let's look at our streaming methods. Here's where we call the Now let's look at our streaming methods. Here's where we call the
@ -329,32 +332,37 @@ response-streaming method `ListFeatures`, which results in our client app
receiving a stream of geographical `RTGFeature`s: receiving a stream of geographical `RTGFeature`s:
```objective-c ```objective-c
[service listFeaturesWithRequest:rectangle
eventHandler:^(BOOL done, RTGFeature *response, NSError *error) { - (void)didReceiveProtoMessage(GPBMessage *)message {
if (response) { if (message) {
NSLog(@"Found feature at %@ called %@.", response.location, response.name); NSLog(@"Found feature at %@ called %@.", response.location, response.name);
} else if (error) { }
}
- (void)didCloseWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error {
if (error) {
NSLog(@"RPC error: %@", error); NSLog(@"RPC error: %@", error);
} }
}]; }
- (void)execRequest {
...
[[service listFeaturesWithMessage:rectangle responseHandler:self callOptions:nil] start];
}
``` ```
Notice how the signature of the handler block now includes a `BOOL done` Notice that instead of providing a response handler object, the view controller
parameter. The handler block can be called any number of times; only on the last object itself handles the responses. The method `didReceiveProtoMessage:` is
call is the `done` argument value set to `YES`. If an error occurs, the RPC called when there's a message received; it can be called any number of times.
finishes and the handler is called with the arguments `(YES, nil, error)`. The method `didCloseWithTrailingMetadata:` is called when the call is complete
and the gRPC status is received from the server (or when there's any error
happens during the call).
The request-streaming method `RecordRoute` expects a stream of `RTGPoint`s from The request-streaming method `RecordRoute` expects a stream of `RTGPoint`s from
the cient. This stream is passed to the method as an object that conforms to the the cient. This stream can be written to the gRPC call object after the call
`GRXWriter` protocol. The simplest way to create one is to initialize one from a starts.
`NSArray` object:
```objective-c ```objective-c
#import <gRPC/GRXWriter+Immediate.h>
...
RTGPoint *point1 = [RTGPoint message]; RTGPoint *point1 = [RTGPoint message];
point.latitude = 40E7; point.latitude = 40E7;
point.longitude = -74E7; point.longitude = -74E7;
@ -363,41 +371,59 @@ RTGPoint *point2 = [RTGPoint message];
point.latitude = 40E7; point.latitude = 40E7;
point.longitude = -74E7; point.longitude = -74E7;
GRXWriter *locationsWriter = [GRXWriter writerWithContainer:@[point1, point2]]; GRPCUnaryResponseHandler *handler =
[[GRPCUnaryResponseHandler alloc] initWithResponseHandler:
[service recordRouteWithRequestsWriter:locationsWriter handler:^(RTGRouteSummary *response, NSError *error) { ^(RTGRouteSummary *response, NSError *error) {
if (response) { if (response) {
NSLog(@"Finished trip with %i points", response.pointCount); NSLog(@"Finished trip with %i points", response.pointCount);
NSLog(@"Passed %i features", response.featureCount); NSLog(@"Passed %i features", response.featureCount);
NSLog(@"Travelled %i meters", response.distance); NSLog(@"Travelled %i meters", response.distance);
NSLog(@"It took %i seconds", response.elapsedTime); NSLog(@"It took %i seconds", response.elapsedTime);
} else { } else {
NSLog(@"RPC error: %@", error); NSLog(@"RPC error: %@", error);
} }
}]; }
responseDispatchQueue:nil];
GRPCStreamingProtoCall *call =
[service recordRouteWithResponseHandler:handler callOptions:nil];
[call start];
[call writeMessage:point1];
[call writeMessage:point2];
[call finish];
``` ```
The `GRXWriter` protocol is generic enough to allow for asynchronous streams, streams of future values, or even infinite streams. Note that since the gRPC call object does not know the end of the request
stream, users must invoke `finish:` method when the request stream is complete.
Finally, let's look at our bidirectional streaming RPC `RouteChat()`. The way to 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 call a bidirectional streaming RPC is just a combination of how to call
request-streaming RPCs and response-streaming RPCs. request-streaming RPCs and response-streaming RPCs.
```objective-c ```objective-c
[service routeChatWithRequestsWriter:notesWriter handler:^(BOOL done, RTGRouteNote *note, NSError *error) {
- (void)didReceiveProtoMessage(GPBMessage *)message {
RTGRouteNote *note = (RTGRouteNote *)message;
if (note) { if (note) {
NSLog(@"Got message %@ at %@", note.message, note.location); NSLog(@"Got message %@ at %@", note.message, note.location);
} else if (error) {
NSLog(@"RPC error: %@", error);
} }
if (done) { }
- (void)didCloseWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error {
if (error) {
NSLog(@"RPC error: %@", error);
} else {
NSLog(@"Chat ended."); NSLog(@"Chat ended.");
} }
}]; }
```
The semantics for the handler block and the `GRXWriter` argument here are - (void)execRequest {
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 GRPCStreamingProtoCall *call =
order they were written, the two streams operate completely independently. [service routeChatWithResponseHandler:self callOptions:nil];
[call start];
[call writeMessage:note1];
...
[call writeMessage:noteN];
[call finish];
}
```