版权声明
本文由陈怀哲首发自简书:http://www.jianshu.com/users/9f2e536b78fd/latest_articles;
微信公众号:陈怀哲(chenhuaizhe2016);
无需授权即可转载,但请自觉保留以上版权声明。

好友和聊天流程图

在看这篇文章之前,你需要配置好服务器,以及完成注册和登录的基本功能,才能继续好友和聊天的操作。

下面两篇文章是环境配置和注册、登录功能的详细介绍:
XMPP的mysql和openfire环境配置
iOS中XMPP简单聊天实现 注册和登录

另外必须了解一些CoreData相关知识

好友

  1. 点击登录之后,验证成功就会跳到好友页面。这个时候需要显示你已经有的好友。
    那么在tableViewCell中显示好友姓名,需要数据源,数据源从服务器获看你是否有好友,检索到你的好友后把他显示在列表上。
    xmpp中管理好友的类是 XMPPRoster,并且使用coredata来储存好友,达到数据持久化的效果。
    那么我们可以将获取储存好友的仓库和xmppRoster对象的初始化封装在XMPPManager中。
    在.h文件中声明:

    //好友管理
    @property(nonatomic,strong)XMPPRoster xmppRoster;

    遵循代理:

    @interface XMPPManager : NSObject<XMPPStreamDelegate,XMPPRosterDelegate>

    在 .m文件中重写init方法中:

    //2.好友管理//获得一个存储好友的CoreData仓库,用来数据持久化    XMPPRosterCoreDataStorage rosterCoreDataStorage = [XMPPRosterCoreDataStorage sharedInstance];//初始化xmppRoster    self.xmppRoster = [[XMPPRoster alloc]initWithRosterStorage:rosterCoreDataStorage dispatchQueue:dispatch_get_main_queue()];//激活   [self.xmppRoster activate:self.xmppStream];//设置代理  [self.xmppRoster addDelegate:self delegateQueue:dispatch_get_main_queue()];
  2. 接收好友请求。
    将接收到好友请求的方法也封装在XMPPManager中:

    // 收到好友请求执行的方法-(void)xmppRoster:(XMPPRoster )sender didReceivePresenceSubscriptionRequest:(XMPPPresence )presence{ self.fromJid = presence.from; UIAlertView alert = [[UIAlertView alloc]initWithTitle:@"提示:有人添加你" message:presence.from.user  delegate:self cancelButtonTitle:@"拒绝" otherButtonTitles:@"OK", nil]; [alert show];}
    -(void)alertView:(UIAlertView )alertView clickedButtonAtIndex:(NSInteger)buttonIndex{  switch (buttonIndex) {   case 0:   [self.xmppRoster rejectPresenceSubscriptionRequestFrom:self.fromJid];  break;   case 1:   [self.xmppRoster acceptPresenceSubscriptionRequestFrom:self.fromJid andAddToRoster:YES];   break;   default:   break; }}
  3. 添加好友,添加的好友必须是服务器上存在的用户,需要看对方是否同意。对方同意之后,刷新好友列表,显示出来,同时在服务器上也要添加,这里服务器上用的是coredata来存储个人的好友信息。

好友页面实现文件,遵循代理,数据源数组

在viewDidLoad中完成初始化数组,设置代理和添加好友按钮

这里简化了添加好友,写死了只能添加“张三”,如果需要添加更多,可以写成借口

接下来是tableview数据源代理方法

tableview

这时候数组明显是没有jid对象的。获取jid对象是在XMPPPRoster代理方法中实现的:

pragma mark xmppRoster 的代理方法

pragma mark 开始检索好友列表的方法-(void)xmppRosterDidBeginPopulating:(XMPPRoster *)sender{    NSLog(@"开始检索好友列表");}
pragma mark 正在检索好友列表的方法-(void)xmppRoster:(XMPPRoster )sender didRecieveRosterItem:(DDXMLElement )item{    NSLog(@"每一个好友都会走一次这个方法");//获得item的属性里的jid字符串,再通过它获得jid对象    NSString jidStr = [[item attributeForName:@"jid"] stringValue];    XMPPJID jid = [XMPPJID jidWithString:jidStr];//是否已经添加    if ([self.rosterJids containsObject:jid]) {        return;    }//将好友添加到数组中去    [self.rosterJids addObject:jid];//添加完数据要更新UI(表视图更新)    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self.rosterJids.count-1 inSection:0];    [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];}
pragma mark 好友列表检索完毕的方法-(void)xmppRosterDidEndPopulating:(XMPPRoster )sender{    NSLog(@"好友列表检索完毕");}

4. 删除好友。列表删除,数组删除,服务器删除。

pragma mark 删除好友执行的方法-(void)tableView:(UITableView )tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath )indexPath{    if (editingStyle==UITableViewCellEditingStyleDelete) { //找到要删除的人        XMPPJID jid = self.rosterJids[indexPath.row];//从数组中删除        [self.rosterJids removeObjectAtIndex:indexPath.row];//从Ui单元格删除        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic         ];//从服务器删除        [[XMPPManager defaultManager].xmppRoster removeUser:jid];    }}

5.进入聊天页面

点击进入聊天页面的方法

聊天页面接受jid值的属性

聊天

1.发送普通文本消息
同样在XMPPManager中进行封装;

//聊天信息归档
@property(nonatomic,strong)XMPPMessageArchiving xmppMessageArchiving;
//信息归档的上下文
@property(nonatomic,strong)NSManagedObjectContext
messageArchivingContext;

在init初始化时:

//3.保存聊天记录  //初始化一个仓库        XMPPMessageArchivingCoreDataStorage *messageStorage = [XMPPMessageArchivingCoreDataStorage sharedInstance];  //创建一个消息归档对象        self.xmppMessageArchiving = [[XMPPMessageArchiving alloc]initWithMessageArchivingStorage:messageStorage dispatchQueue:dispatch_get_main_queue()];  //激活        [self.xmppMessageArchiving activate:self.xmppStream];  //上下文        self.messageArchivingContext = messageStorage.mainThreadManagedObjectContext;

在聊天页面的viewDidload中:

 

发送普通消息:

-(void)doSend{    //创建一个消息对象,并且指明接收者    XMPPMessage *message = [XMPPMessage messageWithType:@"chat" to:self.chatToJid];    //设置消息内容    [message addBody:@"呵呵呵呵呵呵呵呵呵呵"];    //发送消息    [[XMPPManager defaultManager].xmppStream sendElement:message];    //发送成功或者失败,有两种对应的代理方法}

消息发送是否成功,会走下面的代理方法:

xmppStream的代理方法
刷新消息的方法,需要熟悉CoreData知识
#pragma mark 刷新消息的方法-(void)reloadMessage{              //得到上下文    NSManagedObjectContext context = [XMPPManager defaultManager].messageArchivingContext;              //搜索对象    NSFetchRequest request = [[NSFetchRequest alloc]init];             //创建一个实体描述    NSEntityDescription entity = [NSEntityDescription entityForName:@"XMPPMessageArchiving_Message_CoreDataObject" inManagedObjectContext:context];    [request setEntity:entity];            //查询条件    NSPredicate pre = [NSPredicate predicateWithFormat:@"streamBareJidStr = %@ AND bareJidStr = %@",[XMPPManager defaultManager].xmppStream.myJID.bare,self.chatToJid.bare];    request.predicate = pre;           //排序方式    NSSortDescriptor sort = [[NSSortDescriptor alloc]initWithKey:@"timestamp" ascending:YES];    request.sortDescriptors = @[sort];           //执行查询    NSError error = nil;   NSArray array = [context executeFetchRequest:request error:&error];    if (self.messages.count != 0) {        [self.messages removeAllObjects];    }     [self.messages addObjectsFromArray:array];     [self.tableView reloadData];}

2.显示聊天记录

- (NSInteger)tableView:(UITableView )tableView numberOfRowsInSection:(NSInteger)section {
return self.messages.count;
}
- (UITableViewCell )tableView:(UITableView )tableView cellForRowAtIndexPath:(NSIndexPath )indexPath {    static NSString cellIndentifier = @"cell";    UITableViewCell cell = [tableView dequeueReusableCellWithIdentifier:cellIndentifier];    if (cell==nil) {     cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIndentifier];    }   //将聊天信息放到cell上    //拿到一个聊天消息    XMPPMessageArchiving_Message_CoreDataObject message = self.messages[indexPath.row];    if (message.isOutgoing == YES) {     cell.detailTextLabel.text = message.body;     }    }else{     cell.textLabel.text = message.body;    }    return cell;}

成功后就可以聊天了:

演示图

3.发送图片等消息(重点)
发送视频等其他文件也是一样,xmpp中需要将图片转化成NSData,然后转化成成base64的字符串进行传输,然后接收到之后再反转化成图片。
首先要访问系统相册。

遵循代理:

@interface ChatViewController ()<XMPPStreamDelegate,UIImagePickerControllerDelegate,UINavigationControllerDelegate>

从系统相册选择照片

发送图片消息

这时候需要更改cellForRowAtIndexPath:方法,注意红色部分。

发送图片消息对应cell里也需要更改

我把图片设置为cell的imageView,所以图片显示了在左边,说明图片消息发送是成功的,视频等其他类型的消息,也是同样的原理。

图片消息演示

到这里,简单的聊天功能就实现了,了解了基本原理和操作,我们自己还可以加入更多的自定义,从而优化得更好。这里仅仅讲述了一些基本的方法,如果想了解更多,赶快自己动手实践吧

文/陈怀哲(简书作者)
原文链接:http://www.jianshu.com/p/8894a5a71b70
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

iOS中XMPP简单聊天实现 好友和聊天的更多相关文章

  1. iOS中 XMPP即时通讯实现的主要步骤

    这里只是列出实现的只要步骤,不是全部代码. 首先导入XMPPFramework,及相关配置,完成后开始. 创建一个XMPPHelper  类来管理要进行的操作. XMPPHelper.h文件如下 ty ...

  2. IOS中一个简单的粒子效果实现

    1.效果图展示 2.实现思路 1> 首先要实现上面的效果,第一步要处理的就是一个简单的画板,在View上面用鼠标滑动的时候画出线条,这个功能可使用UIBezierPath实现 2> 关于粒 ...

  3. iOS中 超简单抽屉效果(MMDrawerController)的实现

    ios开发中,展示类应用通常要用到抽屉效果,由于项目需要,本人找到一个demo,缩减掉一些不常用的功能,整理出一个较短的实例. 首先需要给工程添加第三方类库 MMDrawerController: 这 ...

  4. ios中XMPP的搭建

    1 首先下载xmppframework这个框架 https://github.com/robbiehanson/XMPPFramework   2 环境配置 参考:https://github.com ...

  5. 正则表达式在iOS中的运用

    1.什么是正则表达式 正则表达式,又称正规表示法,是对字符串操作的一种逻辑公式.正则表达式可以检测给定的字符串是否符合我们定义的逻辑,也可以从字符串中获取我们想要的特定部分.它可以迅速地用极简单的方式 ...

  6. iOS中的主要框架framework

    在日常的iOS项目开发中,主要使用的就是Foundation和UIKit这两个框架. (一)Foundation框架 Foundation是对Core Foundation框架的一个封装,使用Foun ...

  7. iOS开发拓展篇-XMPP简单介绍

    iOS开发拓展篇-XMPP简单介绍 一.即时通讯简单介绍 1.简单说明 即时通讯技术(IM)支持用户在线实时交谈.如果要发送一条信息,用户需要打开一个小窗口,以便让用户及其朋友在其中输入信息并让交谈双 ...

  8. iOS开发——网络编程OC篇&(一)XMPP简单介绍与准备

    XMPP简单介绍与准备 一.即时通讯简单介绍 1.简单说明 即时通讯技术(IM)支持用户在线实时交谈.如果要发送一条信息,用户需要打开一个小窗口,以便让用户及其朋友在其中输入信息并让交谈双方都看到交谈 ...

  9. iOS开发UI篇—使用UItableview完成一个简单的QQ好友列表(一)

    iOS开发UI篇—使用UItableview完成一个简单的QQ好友列表(一) 一.项目结构和plist文件 二.实现代码 1.说明: 主控制器直接继承UITableViewController // ...

随机推荐

  1. Sorting File Contents and Output with sort

     Sorting File Contents and Output with sort   Another very useful command to use on text file is  so ...

  2. PC端QQ协议解析之0825

    QQ协议0825代号解析,包括客户端发送包和服务器发送包. 主要借鉴的此篇文章,我自己也是重复造轮子. 基本信息 操作系统:windows7 QQ-Version:3643 客户端到服务器: 02:数 ...

  3. MaraDNS与DeadWood一起配置为本地机器提供小型化DNS服务

    因为工作测试需要,要在本机装一个环境,可以解析自己命名的域名,即域名->IP的映射服务.在网上找了下,都说是MaraDNS不错.也试了下,在本地配置是没有问题的.从官网上下载的是2-0-11.w ...

  4. 【转】Multithreaded Python Tutorial with the “Threadworms” Demo

    The code for this tutorial can be downloaded here: threadworms.py or from GitHub. This code works wi ...

  5. MVC验证码的编写

    主要是相互学习一下mvc,希望各位大神指导 /// <summary> /// 生成随机数字 /// </summary> /// <returns>随机数字< ...

  6. IIS应用程序池数目

    今天突然遇到一个问题,访问线上站点,数据处理过之后,访问页面有时是404,有时不是404,而404页面刷新几次之后就正常了. 经过大神们指点之后,发现竟然是应用程序池惹的祸. 分析下原因,在代码里面数 ...

  7. 使用 HTML5 设计辅助功能

    使用 HTML5 设计辅助功能 Rajesh Lal 下载代码示例 如果您真的对面向广大受众感兴趣,将需要为网站设计辅助功能. 辅助功能使网页更易于访问.更易于使用,可供每个人浏览. 通常,使用最新的 ...

  8. 我自己的style

    /** DATE:Time AUTHOR:Zoe TEAM:公司名称 INTRO:cssName **/ @charset "utf-8"; /*通用公共样式 开始*/ /* 清除 ...

  9. htmlspecialchars()函数

    htmlspecialchars() 函数把一些预定义的字符转换为 HTML 实体. 预定义的字符是: & (和号) 成为 & " (双引号) 成为 " ' (单引 ...

  10. logisticregression

    from numpy import * import random import time st = time.time() def loaddata(filename): fr = open(''. ...