GCDAsyncSocket编程

同上一篇文章一样,这里也是使用Socket实现一个聊天室,但是这里使用的是一个常用的框架实现的:GCDAsyncSocket

一:导入这个框架

二:声明这个Socket的成员变量,定义一个消息数组  

 @interface ViewController ()<UITextFieldDelegate,UITableViewDataSource,UITableViewDelegate,GCDAsyncSocketDelegate>{

     GCDAsyncSocket *_socket;
 }
 @property (weak, nonatomic) IBOutlet NSLayoutConstraint *inputViewConstraint;
 @property (weak, nonatomic) IBOutlet UITableView *tableView;

 @property (nonatomic, strong) NSMutableArray *chatMsgs;//聊天消息数组

 @end

懒加载消息数组

 -(NSMutableArray *)chatMsgs{
     if (!_chatMsgs) {
         _chatMsgs = [NSMutableArray array];
     }

     return _chatMsgs;
 }

三:链接服务器

 - (IBAction)connectToHost:(id)sender {
     // 1.建立连接
     NSString *host = @"127.0.0.1";
     ;

     // 创建一个Socket对象
     _socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, )];

     // 连接
     NSError *error = nil;
     [_socket connectToHost:host onPort:port error:&error];
     if (error) {
         NSLog(@"%@",error);
     }
 }

链接与断开连接的代理方法

 #pragma mark -AsyncSocket的代理
 #pragma mark 连接主机成功
 -(void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port{
     NSLog(@"连接主机成功");
 }

 #pragma mark 与主机断开连接
 -(void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err{

     if(err){
         NSLog(@"断开连接 %@",err);
     }
 }

四:登陆

 - (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];
     // 发送登录指令给服务
     [_socket writeData:data withTimeout:- tag:];
 }

五:发送数据

 -(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];

     // 发送数据
     [_socket writeData:data withTimeout:- tag:];

     // 发送完数据,清空textField
     textField.text = nil;

     return YES;
 }

 #pragma mark 数据成功发送到服务器
 -(void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag{
     NSLog(@"数据成功发送到服务器");
     //数据发送成功后,自己调用一下读取数据的方法,接着_socket才会调用下面的代理方法
     [_socket readDataWithTimeout:- tag:tag];
 }

 #pragma mark 服务器有数据,会调用这个方法
 -(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
     // 从服务器接收到的数据
     NSString *recStr =  [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

     NSLog(@"%@ %ld %@",[NSThread currentThread],tag, recStr);

     ) {//聊天返回的数据
         // 刷新表格
         [self reloadDataWithText:recStr];
     }
 //    }else if(tag == 101 ){//登录返回数据,不应该把数据添加到表格里
 //
 //
 //    }

 }

六:加载聊天数据到界面,并且实现滚动到对应的位置,键盘的键盘

 -(void)reloadDataWithText:(NSString *)text{
     [self.chatMsgs addObject:text];

     // UI刷新要主线程
     dispatch_async(dispatch_get_main_queue(), ^{
         [self.tableView reloadData];

         // 数据多,应该往上滚动
         NSIndexPath *lastPath = [NSIndexPath indexPathForRow:self.chatMsgs.count -  inSection:];
         [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];
 }

键盘处理

     // 监听键盘
     [[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;
 }
 

iOS开发——网络编程OC篇&GCDAsyncSocket编程的更多相关文章

  1. iOS开发——网络实用技术OC篇&网络爬虫-使用青花瓷抓取网络数据

    网络爬虫-使用青花瓷抓取网络数据 由于最近在研究网络爬虫相关技术,刚好看到一篇的的搬了过来! 望谅解..... 写本文的契机主要是前段时间有次用青花瓷抓包有一步忘了,在网上查了半天也没找到写的完整的教 ...

  2. iOS开发——网络实用技术OC篇&网络爬虫-使用java语言抓取网络数据

    网络爬虫-使用java语言抓取网络数据 前提:熟悉java语法(能看懂就行) 准备阶段:从网页中获取html代码 实战阶段:将对应的html代码使用java语言解析出来,最后保存到plist文件 上一 ...

  3. ios开发——实用技术篇OC篇&iOS的主要框架

    iOS的主要框架         阅读目录 Foundation框架为所有的应用程序提供基本系统服务 UIKit框架提供创建基于触摸用户界面的类 Core Data框架管着理应用程序数据模型 Core ...

  4. iOS开发——高级技术OC篇&运行时(Runtime)机制

    运行时(Runtime)机制 本文将会以笔者个人的小小研究为例总结一下关于iOS开发中运行时的使用和常用方法的介绍,关于跟多运行时相关技术请查看笔者之前写的运行时高级用法及相关语法或者查看响应官方文档 ...

  5. iOS开发——UI精选OC篇&UIApplication,UIWindow,UIViewController,UIView(layer)简单介绍

    UIApplication,UIWindow,UIViewController,UIView(layer)简单介绍 一:UIApplication:单例(关于单例后面的文章中会详细介绍,你现在只要知道 ...

  6. iOS开发——运行时OC篇&使用运行时获取系统的属性:使用自己的手势修改系统自带的手势

    使用运行时获取系统的属性:使用自己的手势修改系统自带的手势 有的时候我需要实现一个功能,但是没有想到很好的方法或者想到了方法只是那个方法实现起来太麻烦,一或者确实为了装逼,我们就会想到iOS开发中最牛 ...

  7. iOS开发——高级UI—OC篇&退出键盘

    退出键盘 iOS开发中键盘的退出方法用很多中我们应该在合适的地方使用合适的方法才能更好的提高开发的效率和应用的性能 下面给大家介绍几种最常用的键盘退出方法,基本上iOS开发中的键盘退出方法都是这几种中 ...

  8. iOS开发——网络编程OC篇&Socket编程

    Socket编程 一.网络各个协议:TCP/IP.SOCKET.HTTP等 网络七层由下往上分别为物理层.数据链路层.网络层.传输层.会话层.表示层和应用层. 其中物理层.数据链路层和网络层通常被称作 ...

  9. iOS开发——新特性OC篇&Swift 2.0新特性

    Swift 2.0新特性     转眼间,Swift已经一岁多了,这门新鲜.语法时尚.类型安全.执行速度更快的语言已经渐渐的深入广大开发者的心.我同样也是非常喜爱这门新的编程语言. 今年6月,一年一度 ...

随机推荐

  1. 深入理解Java虚拟机 - Java体系

    使用JAVA已经快三年了,但说来惭愧,一直以来认为Java就是Java语言本身,最多再包括一个JVM,对于整个Java的体系结构还是不甚明了,现在有时间把<深入理解Java虚拟机>这本书读 ...

  2. bzoj3170

    以前写的,好像忘写解题报告 注意是一个跟曼哈顿距离很有用的结论 |xi-xj|+|yi-yj|=max(|xi+yi-(xj+yj)|,|xi-yi+(xj-yj)|) 因为绝对值有个性质是|a-b| ...

  3. 浏览器兼容问题系列---使IE支持CSS3 Media Quary

    兼容是一件很让前端攻城师头疼的事情,笔者今天在做一个Demo的时候就碰到了一个问题(大牛就不要拍砖了,谢谢!) 经常做移动互联网前端的攻城师想必对于css3 media quary已经很熟悉了,但是碰 ...

  4. C#控件背景透明的几种解决方案

    已经很少做winform程序了,最新参与了一个小项目,遇到了控件背景透明的功能要求,特在此总结一下,供有需要的同行参考. 0.背景透明的概念和分类 背景透明是啥意思呢,就是背景透明.哈哈,废话了.其实 ...

  5. BZOJ_1027_[JSOI2007]_合金_(计算几何+Floyd求最小环)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1027 共三种金属,\(m\)种材料,给出每种材料中三种金属的占比. 给出\(n\)种合金的三种 ...

  6. 【express】

    app.use(express.favicon(__dirname + '/public/images/favicon.ico'));不支持png格式

  7. 【 D3.js 高级系列 — 5.1 】 颜色插值和线性渐变

    颜色插值指的是给出两个 RGB 颜色值,两个颜色之间的值通过插值函数计算得到.线性渐变是添加到 SVG 图形上的过滤器,只需给出两端的颜色值即可. 1. 颜色插值 在[高级 - 第 5.0 章]里已经 ...

  8. Java [leetcode 37]Sudoku Solver

    题目描述: Write a program to solve a Sudoku puzzle by filling the empty cells. Empty cells are indicated ...

  9. 在FOR中使用close window,循环次数大于1就会报异常

    在FOR循环中执行以下动作: 场景:1.打开页面A,    2.点击A中的链接打开新的window, 3.将driver切换到新window, 4.close window 5.再切换到页面A 时出异 ...

  10. API性能测试基本性能指标及要求

    略 适用 Lifeix 所有后台应用. 1.事务(Transaction) 在web性能测试中,一个事务表示一个“从用户发送请求->web server接受到请求,进行处理-> web s ...