xref: /aosp_15_r20/external/grpc-grpc/examples/objective-c/route_guide/ViewControllers.m (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1/*
2 *
3 * Copyright 2015 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19#import <UIKit/UIKit.h>
20#if COCOAPODS
21#import <RouteGuide/RouteGuide.pbrpc.h>
22#else
23#import "examples/protos/RouteGuide.pbrpc.h"
24#endif
25
26#import <GRPCClient/GRPCTransport.h>
27
28static NSString *const kHostAddress = @"localhost:50051";
29
30/** Category to override RTGPoint's description. */
31@interface RTGPoint (Description)
32- (NSString *)description;
33@end
34
35@implementation RTGPoint (Description)
36- (NSString *)description {
37  NSString *verticalDirection = self.latitude >= 0 ? @"N" : @"S";
38  NSString *horizontalDirection = self.longitude >= 0 ? @"E" : @"W";
39  return
40      [NSString stringWithFormat:@"%.02f%@ %.02f%@", abs(self.latitude) / 1E7f, verticalDirection,
41                                 abs(self.longitude) / 1E7f, horizontalDirection];
42}
43@end
44
45/** Category to give RTGRouteNote a convenience constructor. */
46@interface RTGRouteNote (Constructors)
47+ (instancetype)noteWithMessage:(NSString *)message
48                       latitude:(float)latitude
49                      longitude:(float)longitude;
50@end
51
52@implementation RTGRouteNote (Constructors)
53+ (instancetype)noteWithMessage:(NSString *)message
54                       latitude:(float)latitude
55                      longitude:(float)longitude {
56  RTGRouteNote *note = [self message];
57  note.message = message;
58  note.location.latitude = (int32_t)latitude * 1E7;
59  note.location.longitude = (int32_t)longitude * 1E7;
60  return note;
61}
62@end
63
64#pragma mark Demo: Get Feature
65
66/**
67 * Run the getFeature demo. Calls getFeature with a point known to have a feature and a point known
68 * not to have a feature.
69 */
70@interface GetFeatureViewController : UIViewController
71
72@property(weak, nonatomic) IBOutlet UILabel *outputLabel;
73
74@end
75
76@implementation GetFeatureViewController {
77  RTGRouteGuide *_service;
78}
79
80- (void)execRequest {
81  void (^handler)(RTGFeature *response, NSError *error) = ^(RTGFeature *response, NSError *error) {
82    // TODO(makdharma): Remove boilerplate by consolidating into one log function.
83    if (response.name.length) {
84      NSString *str =
85          [NSString stringWithFormat:@"%@\nFound feature called %@ at %@.", self.outputLabel.text,
86                                     response.location, response.name];
87      self.outputLabel.text = str;
88      NSLog(@"Found feature called %@ at %@.", response.name, response.location);
89    } else if (response) {
90      NSString *str = [NSString stringWithFormat:@"%@\nFound no features at %@",
91                                                 self.outputLabel.text, response.location];
92      self.outputLabel.text = str;
93      NSLog(@"Found no features at %@", response.location);
94    } else {
95      NSString *str =
96          [NSString stringWithFormat:@"%@\nRPC error: %@", self.outputLabel.text, error];
97      self.outputLabel.text = str;
98      NSLog(@"RPC error: %@", error);
99    }
100  };
101
102  RTGPoint *point = [RTGPoint message];
103  point.latitude = 409146138;
104  point.longitude = -746188906;
105
106  GRPCUnaryProtoCall *call = [_service
107      getFeatureWithMessage:point
108            responseHandler:[[GRPCUnaryResponseHandler alloc] initWithResponseHandler:handler
109                                                                responseDispatchQueue:nil]
110                callOptions:nil];
111  [call start];
112  call = [_service
113      getFeatureWithMessage:[RTGPoint message]
114            responseHandler:[[GRPCUnaryResponseHandler alloc] initWithResponseHandler:handler
115                                                                responseDispatchQueue:nil]
116                callOptions:nil];
117  [call start];
118}
119
120- (void)viewDidLoad {
121  [super viewDidLoad];
122
123  GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init];
124  options.transport = GRPCDefaultTransportImplList.core_insecure;
125
126  _service = [[RTGRouteGuide alloc] initWithHost:kHostAddress callOptions:options];
127}
128
129- (void)viewDidAppear:(BOOL)animated {
130  self.outputLabel.text = @"RPC log:";
131  self.outputLabel.numberOfLines = 0;
132  self.outputLabel.font = [UIFont fontWithName:@"Helvetica Neue" size:8.0];
133  [self execRequest];
134}
135
136@end
137
138#pragma mark Demo: List Features
139
140/**
141 * Run the listFeatures demo. Calls listFeatures with a rectangle containing all of the features in
142 * the pre-generated database. Prints each response as it comes in.
143 */
144@interface ListFeaturesViewController : UIViewController <GRPCProtoResponseHandler>
145
146@property(weak, nonatomic) IBOutlet UILabel *outputLabel;
147
148@end
149
150@implementation ListFeaturesViewController {
151  RTGRouteGuide *_service;
152}
153
154- (dispatch_queue_t)dispatchQueue {
155  return dispatch_get_main_queue();
156}
157
158- (void)execRequest {
159  RTGRectangle *rectangle = [RTGRectangle message];
160  rectangle.lo.latitude = 405E6;
161  rectangle.lo.longitude = -750E6;
162  rectangle.hi.latitude = 410E6;
163  rectangle.hi.longitude = -745E6;
164
165  NSLog(@"Looking for features between %@ and %@", rectangle.lo, rectangle.hi);
166  GRPCUnaryProtoCall *call = [_service listFeaturesWithMessage:rectangle
167                                               responseHandler:self
168                                                   callOptions:nil];
169  [call start];
170}
171
172- (void)didReceiveProtoMessage:(GPBMessage *)message {
173  RTGFeature *response = (RTGFeature *)message;
174  if (response) {
175    NSString *str =
176        [NSString stringWithFormat:@"%@\nFound feature at %@ called %@.", self.outputLabel.text,
177                                   response.location, response.name];
178    self.outputLabel.text = str;
179    NSLog(@"Found feature at %@ called %@.", response.location, response.name);
180  }
181}
182
183- (void)didCloseWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error {
184  if (error) {
185    NSString *str = [NSString stringWithFormat:@"%@\nRPC error: %@", self.outputLabel.text, error];
186    self.outputLabel.text = str;
187    NSLog(@"RPC error: %@", error);
188  }
189}
190
191- (void)viewDidLoad {
192  [super viewDidLoad];
193
194  GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init];
195  options.transport = GRPCDefaultTransportImplList.core_insecure;
196
197  _service = [[RTGRouteGuide alloc] initWithHost:kHostAddress callOptions:options];
198}
199
200- (void)viewDidAppear:(BOOL)animated {
201  self.outputLabel.text = @"RPC log:";
202  self.outputLabel.numberOfLines = 0;
203  self.outputLabel.font = [UIFont fontWithName:@"Helvetica Neue" size:8.0];
204  [self execRequest];
205}
206
207@end
208
209#pragma mark Demo: Record Route
210
211/**
212 * Run the recordRoute demo. Sends several randomly chosen points from the pre-generated feature
213 * database with a variable delay in between. Prints the statistics when they are sent from the
214 * server.
215 */
216@interface RecordRouteViewController : UIViewController
217
218@property(weak, nonatomic) IBOutlet UILabel *outputLabel;
219
220@end
221
222@implementation RecordRouteViewController {
223  RTGRouteGuide *_service;
224}
225
226- (void)execRequest {
227  NSString *dataBasePath = [NSBundle.mainBundle pathForResource:@"route_guide_db" ofType:@"json"];
228  NSData *dataBaseContent = [NSData dataWithContentsOfFile:dataBasePath];
229  NSError *error;
230  NSArray *features = [NSJSONSerialization JSONObjectWithData:dataBaseContent
231                                                      options:0
232                                                        error:&error];
233
234  if (error) {
235    NSLog(@"Error reading database.");
236    NSString *str = @"Error reading database.";
237    self.outputLabel.text = str;
238    return;
239  }
240
241  void (^handler)(RTGRouteSummary *response, NSError *error) =
242      ^(RTGRouteSummary *response, NSError *error) {
243        if (response) {
244          NSString *str = [NSString
245              stringWithFormat:@"%@\nFinished trip with %i points\nPassed %i features\n"
246                                "Travelled %i meters\nIt took %i seconds",
247                               self.outputLabel.text, response.pointCount, response.featureCount,
248                               response.distance, response.elapsedTime];
249          self.outputLabel.text = str;
250          NSLog(@"Finished trip with %i points", response.pointCount);
251          NSLog(@"Passed %i features", response.featureCount);
252          NSLog(@"Travelled %i meters", response.distance);
253          NSLog(@"It took %i seconds", response.elapsedTime);
254        } else {
255          NSString *str =
256              [NSString stringWithFormat:@"%@\nRPC error: %@", self.outputLabel.text, error];
257          self.outputLabel.text = str;
258          NSLog(@"RPC error: %@", error);
259        }
260      };
261
262  // We can use unary response handler here because, despite the requests being a stream, the
263  // response of the RPC is unary.
264  GRPCStreamingProtoCall *call =
265      [_service recordRouteWithResponseHandler:[[GRPCUnaryResponseHandler alloc]
266                                                   initWithResponseHandler:handler
267                                                     responseDispatchQueue:nil]
268                                   callOptions:nil];
269  [call start];
270  for (id feature in features) {
271    RTGPoint *location = [RTGPoint message];
272    location.longitude = [((NSNumber *)feature[@"location"][@"longitude"]) intValue];
273    location.latitude = [((NSNumber *)feature[@"location"][@"latitude"]) intValue];
274    NSString *str =
275        [NSString stringWithFormat:@"%@\nVisiting point %@", self.outputLabel.text, location];
276    self.outputLabel.text = str;
277    NSLog(@"Visiting point %@", location);
278    [call writeMessage:location];
279  }
280  [call finish];
281}
282
283- (void)viewDidLoad {
284  [super viewDidLoad];
285
286  GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init];
287  options.transport = GRPCDefaultTransportImplList.core_insecure;
288
289  _service = [[RTGRouteGuide alloc] initWithHost:kHostAddress callOptions:options];
290}
291
292- (void)viewDidAppear:(BOOL)animated {
293  self.outputLabel.text = @"RPC log:";
294  self.outputLabel.numberOfLines = 0;
295  self.outputLabel.font = [UIFont fontWithName:@"Helvetica Neue" size:8.0];
296  [self execRequest];
297}
298
299@end
300
301#pragma mark Demo: Route Chat
302
303/**
304 * Run the routeChat demo. Send some chat messages, and print any chat messages that are sent from
305 * the server.
306 */
307@interface RouteChatViewController : UIViewController <GRPCProtoResponseHandler>
308
309@property(weak, nonatomic) IBOutlet UILabel *outputLabel;
310
311@end
312
313@implementation RouteChatViewController {
314  RTGRouteGuide *_service;
315}
316
317- (dispatch_queue_t)dispatchQueue {
318  return dispatch_get_main_queue();
319}
320
321- (void)execRequest {
322  NSArray *notes = @[
323    [RTGRouteNote noteWithMessage:@"First message" latitude:0 longitude:0],
324    [RTGRouteNote noteWithMessage:@"Second message" latitude:0 longitude:1],
325    [RTGRouteNote noteWithMessage:@"Third message" latitude:1 longitude:0],
326    [RTGRouteNote noteWithMessage:@"Fourth message" latitude:0 longitude:0]
327  ];
328
329  GRPCStreamingProtoCall *call = [_service routeChatWithResponseHandler:self callOptions:nil];
330  [call start];
331  for (RTGRouteNote *note in notes) {
332    [call writeMessage:note];
333  }
334  [call finish];
335}
336
337- (void)didReceiveProtoMessage:(GPBMessage *)message {
338  RTGRouteNote *note = (RTGRouteNote *)message;
339  if (note) {
340    NSString *str = [NSString stringWithFormat:@"%@\nGot message %@ at %@", self.outputLabel.text,
341                                               note.message, note.location];
342    self.outputLabel.text = str;
343    NSLog(@"Got message %@ at %@", note.message, note.location);
344  }
345}
346
347- (void)didCloseWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error {
348  if (!error) {
349    NSLog(@"Chat ended.");
350  } else {
351    NSString *str = [NSString stringWithFormat:@"%@\nRPC error: %@", self.outputLabel.text, error];
352    self.outputLabel.text = str;
353    NSLog(@"RPC error: %@", error);
354  }
355}
356
357- (void)viewDidLoad {
358  [super viewDidLoad];
359
360  GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init];
361  options.transport = GRPCDefaultTransportImplList.core_insecure;
362
363  _service = [[RTGRouteGuide alloc] initWithHost:kHostAddress callOptions:options];
364}
365
366- (void)viewDidAppear:(BOOL)animated {
367  // TODO(makarandd): Set these properties through UI builder
368  self.outputLabel.text = @"RPC log:";
369  self.outputLabel.numberOfLines = 0;
370  self.outputLabel.font = [UIFont fontWithName:@"Helvetica Neue" size:8.0];
371  [self execRequest];
372}
373
374@end
375