TCViewController.m 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. //
  2. // Copyright 2012 Square Inc.
  3. // Portions Copyright (c) 2016-present, Facebook, Inc.
  4. // All rights reserved.
  5. //
  6. // This source code is licensed under the license found in the
  7. // LICENSE-examples file in the root directory of this source tree.
  8. //
  9. #import "TCViewController.h"
  10. #import <SocketRocket/SocketRocket.h>
  11. #import "TCChatCell.h"
  12. @interface TCMessage : NSObject
  13. - (instancetype)initWithMessage:(NSString *)message incoming:(BOOL)incoming;
  14. @property (nonatomic, copy, readonly) NSString *message;
  15. @property (nonatomic, assign, readonly, getter=isIncoming) BOOL incoming;
  16. @end
  17. @implementation TCMessage
  18. - (instancetype)initWithMessage:(NSString *)message incoming:(BOOL)incoming
  19. {
  20. self = [super init];
  21. if (!self) return self;
  22. _incoming = incoming;
  23. _message = message;
  24. return self;
  25. }
  26. @end
  27. @interface TCViewController () <SRWebSocketDelegate, UITextViewDelegate>
  28. {
  29. SRWebSocket *_webSocket;
  30. NSMutableArray<TCMessage *> *_messages;
  31. }
  32. @end
  33. @implementation TCViewController
  34. ///--------------------------------------
  35. #pragma mark - View
  36. ///--------------------------------------
  37. - (void)viewDidLoad;
  38. {
  39. [super viewDidLoad];
  40. _messages = [[NSMutableArray alloc] init];
  41. }
  42. - (void)viewWillAppear:(BOOL)animated
  43. {
  44. [super viewWillAppear:animated];
  45. [self reconnect:nil];
  46. }
  47. - (void)viewDidAppear:(BOOL)animated
  48. {
  49. [super viewDidAppear:animated];
  50. [_inputView becomeFirstResponder];
  51. }
  52. - (void)viewDidDisappear:(BOOL)animated
  53. {
  54. [super viewDidDisappear:animated];
  55. [_webSocket close];
  56. _webSocket = nil;
  57. }
  58. ///--------------------------------------
  59. #pragma mark - Actions
  60. ///--------------------------------------
  61. - (IBAction)reconnect:(id)sender
  62. {
  63. _webSocket.delegate = nil;
  64. [_webSocket close];
  65. _webSocket = [[SRWebSocket alloc] initWithURL:[NSURL URLWithString:@"wss://echo.websocket.org"]];
  66. _webSocket.delegate = self;
  67. self.title = @"Opening Connection...";
  68. [_webSocket open];
  69. }
  70. - (void)sendPing:(id)sender;
  71. {
  72. [_webSocket sendPing:nil error:NULL];
  73. }
  74. ///--------------------------------------
  75. #pragma mark - Messages
  76. ///--------------------------------------
  77. - (void)_addMessage:(TCMessage *)message
  78. {
  79. [_messages addObject:message];
  80. [self.tableView insertRowsAtIndexPaths:@[ [NSIndexPath indexPathForRow:_messages.count - 1 inSection:0] ]
  81. withRowAnimation:UITableViewRowAnimationNone];
  82. [self.tableView scrollRectToVisible:self.tableView.tableFooterView.frame animated:YES];
  83. }
  84. ///--------------------------------------
  85. #pragma mark - UITableViewController
  86. ///--------------------------------------
  87. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
  88. {
  89. return _messages.count;
  90. }
  91. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
  92. {
  93. TCMessage *message = _messages[indexPath.row];
  94. TCChatCell *cell = [self.tableView dequeueReusableCellWithIdentifier:message.incoming ? @"ReceivedCell" : @"SentCell"
  95. forIndexPath:indexPath];
  96. cell.textView.text = message.message;
  97. cell.nameLabel.text = message.incoming ? @"Other" : @"Me";
  98. return cell;
  99. }
  100. ///--------------------------------------
  101. #pragma mark - SRWebSocketDelegate
  102. ///--------------------------------------
  103. - (void)webSocketDidOpen:(SRWebSocket *)webSocket;
  104. {
  105. NSLog(@"Websocket Connected");
  106. self.title = @"Connected!";
  107. }
  108. - (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error;
  109. {
  110. NSLog(@":( Websocket Failed With Error %@", error);
  111. self.title = @"Connection Failed! (see logs)";
  112. _webSocket = nil;
  113. }
  114. - (void)webSocket:(SRWebSocket *)webSocket didReceiveMessageWithString:(nonnull NSString *)string
  115. {
  116. NSLog(@"Received \"%@\"", string);
  117. [self _addMessage:[[TCMessage alloc] initWithMessage:string incoming:YES]];
  118. }
  119. - (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean;
  120. {
  121. NSLog(@"WebSocket closed");
  122. self.title = @"Connection Closed! (see logs)";
  123. _webSocket = nil;
  124. }
  125. - (void)webSocket:(SRWebSocket *)webSocket didReceivePong:(NSData *)pongPayload;
  126. {
  127. NSLog(@"WebSocket received pong");
  128. }
  129. ///--------------------------------------
  130. #pragma mark - UITextViewDelegate
  131. ///--------------------------------------
  132. - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
  133. {
  134. if ([text rangeOfString:@"\n"].location != NSNotFound) {
  135. NSString *message = [textView.text stringByReplacingCharactersInRange:range withString:text];
  136. message = [message stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
  137. [_webSocket sendString:message error:NULL];
  138. [self _addMessage:[[TCMessage alloc] initWithMessage:message incoming:NO]];
  139. textView.text = nil;
  140. return NO;
  141. }
  142. return YES;
  143. }
  144. @end