---恢復內容開始---數組
#import "ViewController.h" @interface ViewController ()<NSStreamDelegate,UITextFieldDelegate,UITableViewDataSource,UITableViewDelegate>{ NSInputStream *_inputStream;//對應輸入流 NSOutputStream *_outputStream;//對應輸出流 } @property (weak, nonatomic) IBOutlet NSLayoutConstraint *inputViewConstraint; @property (weak, nonatomic) IBOutlet UITableView *tableView; @property (nonatomic, strong) NSMutableArray *chatMsgs;//聊天消息數組 @end @implementation ViewController -(NSMutableArray *)chatMsgs{ if (!_chatMsgs) { _chatMsgs = [NSMutableArray array]; } return _chatMsgs; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. // 2.收發數據 // 作一個聊天 // 1.用戶登陸 // 2.收發數據 // 監聽鍵盤 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(kbFrmWillChange:) name:UIKeyboardWillChangeFrameNotification object:nil]; } -(void)kbFrmWillChange:(NSNotification *)noti{ NSLog(@"%@",noti.userInfo); // 獲取窗口的高度 CGFloat windowH = [UIScreen mainScreen].bounds.size.height; // 鍵盤結束的Frm CGRect kbEndFrm = [noti.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue]; // 獲取鍵盤結束的y值 CGFloat kbEndY = kbEndFrm.origin.y; self.inputViewConstraint.constant = windowH - kbEndY; } -(void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode{ NSLog(@"%@",[NSThread currentThread]); // NSStreamEventOpenCompleted = 1UL << 0,//輸入輸出流打開完成 // NSStreamEventHasBytesAvailable = 1UL << 1,//有字節可讀 // NSStreamEventHasSpaceAvailable = 1UL << 2,//能夠發放字節 // NSStreamEventErrorOccurred = 1UL << 3,// 鏈接出現錯誤 // NSStreamEventEndEncountered = 1UL << 4// 鏈接結束 switch (eventCode) { case NSStreamEventOpenCompleted: NSLog(@"輸入輸出流打開完成"); break; case NSStreamEventHasBytesAvailable: NSLog(@"有字節可讀"); [self readData]; break; case NSStreamEventHasSpaceAvailable: NSLog(@"能夠發送字節"); break; case NSStreamEventErrorOccurred: NSLog(@" 鏈接出現錯誤"); break; case NSStreamEventEndEncountered: NSLog(@"鏈接結束"); // 關閉輸入輸出流 [_inputStream close]; [_outputStream close]; // 從主運行循環移除 [_inputStream removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; [_outputStream removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; break; default: break; } } - (IBAction)connectToHost:(id)sender { // 1.創建鏈接 NSString *host = @"127.0.0.1"; int port = 12345; // 定義C語言輸入輸出流 CFReadStreamRef readStream; CFWriteStreamRef writeStream; CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)host, port, &readStream, &writeStream); // 把C語言的輸入輸出流轉化成OC對象 _inputStream = (__bridge NSInputStream *)(readStream); _outputStream = (__bridge NSOutputStream *)(writeStream); // 設置代理 _inputStream.delegate = self; _outputStream.delegate = self; // 把輸入輸出流添加到主運行循環 // 不添加主運行循環 代理有可能不工做 [_inputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; [_outputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; // 打開輸入輸出流 [_inputStream open]; [_outputStream open]; } - (IBAction)loginBtnClick:(id)sender { // 登陸 // 發送用戶名和密碼 // 在這裏作的時候,只發用戶名,密碼就不用發送 // 若是要登陸,發送的數據格式爲 "iam:zhangsan"; // 若是要發送聊天消息,數據格式爲 "msg:did you have dinner"; //登陸的指令 NSString *loginStr = @"iam:zhangsan"; //把Str轉成NSData NSData *data = [loginStr dataUsingEncoding:NSUTF8StringEncoding]; [_outputStream write:data.bytes maxLength:data.length]; } #pragma mark 讀取服務器返回的數據 -(void)readData{ //創建一個緩衝區 能夠放1024個字節 uint8_t buf[1024]; // 返回實際裝的字節數 NSInteger len = [_inputStream read:buf maxLength:sizeof(buf)]; // 把字節數組轉化成字符串 NSData *data = [NSData dataWithBytes:buf length:len]; // 從服務器接收到的數據 NSString *recStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@",recStr); [self reloadDataWithText:recStr]; } -(BOOL)textFieldShouldReturn:(UITextField *)textField{ NSString *text = textField.text; NSLog(@"%@",text); // 聊天信息 NSString *msgStr = [NSString stringWithFormat:@"msg:%@",text]; //把Str轉成NSData NSData *data = [msgStr dataUsingEncoding:NSUTF8StringEncoding]; // 刷新表格 [self reloadDataWithText:msgStr]; // 發送數據 [_outputStream write:data.bytes maxLength:data.length]; // 發送完數據,清空textField textField.text = nil; return YES; } -(void)reloadDataWithText:(NSString *)text{ [self.chatMsgs addObject:text]; [self.tableView reloadData]; // 數據多,應該往上滾動 NSIndexPath *lastPath = [NSIndexPath indexPathForRow:self.chatMsgs.count - 1 inSection:0]; [self.tableView scrollToRowAtIndexPath:lastPath atScrollPosition:UITableViewScrollPositionBottom animated:YES]; } #pragma mark 表格的數據源 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return self.chatMsgs.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *ID = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; cell.textLabel.text = self.chatMsgs[indexPath.row]; return cell; } -(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{ [self.view endEditing:YES]; } @end
ps:注意:服務器
1.前提須要鏈接服務器oop
2.輸入輸出流須要添加到主運行循環ui
3.輸入流:用來寫數據atom
4.輸出流:用來讀數據代理
步驟總結:orm
1.創建鏈接,設置ip和端口號server
2.經過創建C語言輸入輸出流,鏈接服務器,再把C語言的輸入輸出流轉換成OC對象對象
3.設置OC類型的輸入輸出流代理爲當前控制器blog
4.把輸入輸出流添加到主運行循環當中,打開輸入輸出流
5.客戶端向服務器發送數據(輸出流)
6.服務器向客戶端返回數據(輸入流)
7.當前控制器刷新主界面數據
---恢復內容結束---