参考网址:http://www.jianshu.com/p/8894a5a71b70

借图描述原理:

三、注册、登陆、聊天功能的实现

故事板如下:

四个类如下:

不喜多言,直接上Demo:

LoginViewController.h

#import "ViewController.h"
#import "XMPPManager.h"
#import "RosterViewController.h"
@interface LoginViewController : ViewController<XMPPStreamDelegate> @end

LoginViewController.m

#import "LoginViewController.h"

@interface LoginViewController ()
@property (weak, nonatomic) IBOutlet UITextField *usernameTextField;
@property (weak, nonatomic) IBOutlet UITextField *passwordTextField; @end @implementation LoginViewController - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[[XMPPManager defaultManager].xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()]; }
- (IBAction)login:(UIButton *)sender {
NSLog(@"Click login button");
if (self.usernameTextField.text.length>&&self.passwordTextField.text.length>) { [[XMPPManager defaultManager] loginwithName:self.usernameTextField.text andPassword:self.passwordTextField.text];
}
}
-(void)xmppStreamDidAuthenticate:(XMPPStream *)sender{
NSLog(@"登陆成功");
RosterViewController *roster=[RosterViewController new];
[self.navigationController pushViewController:roster animated:YES]; }
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

RegisterViewController.h

#import "ViewController.h"
#import "XMPPManager.h"
@interface RegisterViewController : ViewController<XMPPStreamDelegate> @end

RegisterViewController.m

#import "RegisterViewController.h"

@interface RegisterViewController ()
@property (weak, nonatomic) IBOutlet UITextField *usernameTextfield;
@property (weak, nonatomic) IBOutlet UITextField *passwordTextfield; @end @implementation RegisterViewController
- (IBAction)register:(UIButton *)sender {
[[XMPPManager defaultManager] registerWithName:self.usernameTextfield.text andPassword:self.passwordTextfield.text];
}
- (IBAction)cancel:(UIButton *)sender {
[self.navigationController popViewControllerAnimated:YES];
}
-(void)xmppStreamDidAuthenticate:(XMPPStream *)sender{ NSLog(@"注册成功!!"); }
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[[XMPPManager defaultManager].xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()]; } - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

RosterViewController.h

#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import "ViewController.h"
#import "XMPPManager.h"
#import "ChatViewController.h"
@interface RosterViewController : ViewController<UITableViewDataSource,UITableViewDelegate,XMPPRosterDelegate>
//存放所有好友的数组
@property(nonatomic,strong) NSMutableArray *rosterJids; @property(nonatomic,strong) UITableView *friendsView; @end

RosterViewController.m

#import "RosterViewController.h"

@interface RosterViewController ()

@end

@implementation RosterViewController

-(UITableView*)friendsView{
if (_friendsView==nil) {
_friendsView=[[UITableView alloc]initWithFrame:CGRectMake(, , self.view.frame.size.width, self.view.frame.size.height) style:UITableViewStylePlain];
_friendsView.dataSource=self;
_friendsView.delegate=self;
}
return _friendsView;
} #pragma mark friendView 代理方法 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return ;
} - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
if (self.rosterJids.count>) {
return self.rosterJids.count;
}
return ; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *ide=@"cell";
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:ide];
if (cell==nil) {
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ide];
}
XMPPJID *jid = self.rosterJids[indexPath.row];
cell.textLabel.text=jid.user;
return cell;
}
#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];
}
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ ChatViewController *chatVC=[ChatViewController new];
chatVC.chatToJid=self.rosterJids[indexPath.row];
[self.navigationController pushViewController:chatVC animated:YES];
} - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
self.rosterJids = [[NSMutableArray alloc]init];
[[XMPPManager defaultManager].xmppRoster addDelegate:self delegateQueue:dispatch_get_main_queue()];
//
UIBarButtonItem *right=[[UIBarButtonItem alloc]initWithTitle:@"添加" style:UIBarButtonItemStylePlain target:self action:@selector(doAdd:)];
self.navigationItem.rightBarButtonItem = right;
[self.view addSubview:self.friendsView]; } //点击添加好友
-(void)doAdd:(UIButton*)sender{
XMPPJID *jid= [XMPPJID jidWithUser:@"admin" domain:@"" resource:nil];
//添加好友
[[XMPPManager defaultManager].xmppRoster subscribePresenceToUser:jid];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} //#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- inSection:]; [self.friendsView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
} @end

ChatViewController.h

#import "ViewController.h"
#import "XMPPManager.h"
@interface ChatViewController : ViewController<XMPPStreamDelegate,UITableViewDataSource,UITableViewDelegate,UIImagePickerControllerDelegate,UINavigationControllerDelegate> @property(nonatomic,strong) XMPPJID *chatToJid; @property(nonatomic,retain) NSMutableArray *messages; @property(nonatomic,strong) UITableView *tableView; @end

ChatViewController.m

#import "ChatViewController.h"

@interface ChatViewController ()

@end

@implementation ChatViewController

- (void)viewDidLoad {
[super viewDidLoad];
self.title=self.chatToJid.user;
self.view.backgroundColor=[UIColor grayColor];
//初始化聊天数组
self.messages=[[NSMutableArray alloc]init];
//设置代理
[[XMPPManager defaultManager].xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
//
[self reloadMessage];
//
UIBarButtonItem *sendMessage=[[UIBarButtonItem alloc]initWithTitle:@"发送" style:UIBarButtonItemStylePlain target:self action:@selector(doSend)];
self.navigationItem.rightBarButtonItem=sendMessage;
[self.view addSubview:self.tableView];
}
-(void)doSend{
/*
//创建一个消息对象,并且指明接收者
XMPPMessage *message = [XMPPMessage messageWithType:@"chat" to:self.chatToJid];
//设置消息内容
[message addBody:@"呵呵呵呵呵呵呵呵呵呵啊啊啊啊啊啊"];
//发送消息
[[XMPPManager defaultManager].xmppStream sendElement:message];
//发送成功或者失败,有两种对应的代理方法
*/ UIImagePickerController *pick=[[UIImagePickerController alloc]init];
pick.delegate=self;
[self presentViewController:pick animated:YES completion:^{ }];
}
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{
//获取相册里的图片
//UIImage *image=info[UIImagePickerControllerOriginalImage];
UIImage *image=[UIImage imageNamed:@"1.png"]; //转化成NSData
NSData *data=UIImagePNGRepresentation(image);
//发送
[self sendImageWithData:data andName:@"图片"]; //
[self dismissViewControllerAnimated:YES completion:nil];
}
-(void)sendImageWithData:(NSData*)data andName:(NSString*)name{
XMPPMessage *message= [XMPPMessage messageWithType:@"chat" to:self.chatToJid];
[message addBody:name];
//
NSString *base64Str=[data base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
//
XMPPElement *attachment=[XMPPElement elementWithName:@"attachment" stringValue:base64Str];
// [message addChild:attachment];
//
[[XMPPManager defaultManager].xmppStream sendElement:message];
}
-(UITableView*)tableView{
if (!_tableView) {
_tableView=[[UITableView alloc]initWithFrame:CGRectMake(, , , self.view.frame.size.height) style:UITableViewStylePlain];
_tableView.dataSource=self;
_tableView.delegate=self;
} return _tableView;
}
#pragma tableView delegate
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return ;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return self.messages.count;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ return ; }
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//NSLog(@"cell");
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];
XMPPMessage *msg=message.message;
if (message.isOutgoing == YES) {
cell.detailTextLabel.text = message.body;
cell.textLabel.text=@"";
for(XMPPElement *node in msg.children){
NSLog(@"图片呢");
//取出消息
NSString *base64Str=node.stringValue;
//NSLog(@"%@",base64Str);
//base64转换成NSData
NSData *data=[[NSData alloc]initWithBase64EncodedString:base64Str options:];
UIImage *image=[[UIImage alloc]initWithData:data];
cell.imageView.image=image;
cell.imageView.frame=CGRectMake(, , , );
cell.imageView.backgroundColor=[UIColor redColor];
} }else{
cell.textLabel.text = message.body;
cell.detailTextLabel.text=@"";
}
// cell.imageView.backgroundColor=[UIColor redColor];
// cell.imageView.image=[UIImage imageNamed:@"1.png"];
return cell; } #pragma mark 聊天的代理方法
-(void)xmppStream:(XMPPStream *)sender didSendMessage:(XMPPMessage *)message{ NSLog(@"消息发送成功");
[self reloadMessage];
}
-(void)xmppStream:(XMPPStream *)sender didFailToSendMessage:(XMPPMessage *)message error:(NSError *)error{
NSLog(@"消息发送失败");
}
-(void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message{ NSLog(@"消息接受成功");
[self reloadMessage];
}
-(void)xmppStream:(XMPPStream *)sender didReceiveError:(DDXMLElement *)error{
NSLog(@"接收失败");
}
#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 != ) {
[self.messages removeAllObjects];
}
[self.messages addObjectsFromArray:array];
[self.tableView reloadData];
if (self.messages.count>) {
NSIndexPath *indexpath=[NSIndexPath indexPathForRow:self.messages.count- inSection:]; [self.tableView scrollToRowAtIndexPath:indexpath atScrollPosition:UITableViewScrollPositionTop animated:YES]; } } - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} @end

运行截图:(基本功能实现,具体细节还需要优化)

xmpp实现的即时通讯聊天(二)的更多相关文章

  1. xmpp实现的即时通讯聊天(一)

    参考网址:http://www.jianshu.com/p/b401ad6ba1a7 http://www.jianshu.com/p/4edbae55a07f 一.mysql和openfire环境的 ...

  2. Openfire XMPP Smack RTC IM 即时通讯 聊天 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  3. IdentityServer4 + SignalR Core +RabbitMQ 构建web即时通讯(二)

    IdentityServer4 + SignalR Core +RabbitMQ 构建web即时通讯(二) IdentityServer4 用户中心生成数据库 上文已经创建了所有的数据库上下文迁移代码 ...

  4. 黑科技!仅需 3 行代码,就能将 Gitter 集成到个人网站中,实现一个 IM 即时通讯聊天室功能?

    欢迎关注个人微信公众号: 小哈学Java, 文末分享阿里 P8 高级架构师吐血总结的 <Java 核心知识整理&面试.pdf>资源链接!! 个人网站: https://www.ex ...

  5. XMPP openfire Smack 即时通讯

    重新整理下这篇文章. 这篇文章的主要任务是使用AndroidStudio,通过Openfire,利用XMPP协议完成一个可以即时通讯.拥有好友系统的聊天软件. 一.服务器配置与相关库 理论不多说,只谈 ...

  6. XMPP协议实现即时通讯底层书写 (一)--从RFC6121阅读開始

    Extensible Messaging and Presence Protocol (XMPP): Instant Messaging and Presence ok,额瑞巴蒂,说好的阅读RFC61 ...

  7. java Activiti6 工作流引擎 websocket 即时聊天 SSM源码 支持手机即时通讯聊天

    即时通讯:支持好友,群组,发图片.文件,消息声音提醒,离线消息,保留聊天记录 (即时聊天功能支持手机端,详情下面有截图) 工作流模块---------------------------------- ...

  8. 开源jabber(XMPP)架设内部即时通讯服务的解决方案

    Jabber 是著名的即时通讯服务服务器,它是一个自由开源软件,能让用户自己架即时通讯服务器,可以在Internet上应用,也可以在局域网中应用.    XMPP(可扩展消息处理现场协议)是基于可扩展 ...

  9. XMPP之ios即时通讯客户端开发-配置XMPP基本信息之工程代码(五)

    登录功能完成以后包含以下代码文件: AppDelegate.h AppDelegate.m LoginViewController.h LoginViewController.m LoginUser. ...

随机推荐

  1. BZOJ 1002--[FJOI2007]轮状病毒(高精度)

    1002: [FJOI2007]轮状病毒 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 6858  Solved: 3745[Submit][Statu ...

  2. Ubuntu16.04安装使用Consul

    Consul 是 HashiCorp 公司推出的开源工具,用于实现分布式系统的服务发现与配置.与其他分布式服务注册与发现的方案,比如 Airbnb 的 SmartStack 等相比,Consul 的方 ...

  3. 再看javascript执行上下文、变量对象

    突然看到一篇远在2010年的老文,作者以章节的形式向我们介绍了ECMA-262-3的部分内容,主要涉及到执行上下文.变量对象.作用域.this等语言细节.内容短小而精悍,文风直白而严谨,读完有酣畅淋漓 ...

  4. ansible 的第一次亲密接触

    如何添加一台机器 编辑 /etc/ansible/hosts 添加本机的 public ssh key 到目标机器的 authorized_keys 添加本机的 私钥 到 ansible 运行 ans ...

  5. VSTO学习(五)——创建Word解决方案

    一.引言 在上一个专题中主要为大家介绍如何自定义我们的Excel 界面的,然而在这个专题中,我将为大家介绍如何用VSTO来创建Word项目,对于Word的VSTO开发和Excel的开发很类似,你同样也 ...

  6. C# 通过IEnumberable接口和IEnumerator接口实现泛型和非泛型自定义集合类型foreach功能

    IEnumerator和IEnumerable的作用 其实IEnumerator和IEnumerable的作用很简单,就是让除数组和集合之外的类型也能支持foreach循环,至于foreach循环,如 ...

  7. Spring Security构建Rest服务-1204-Spring Security OAuth开发APP认证框架之Token处理

    token处理之一基本参数配置 处理token时间.存储策略,客户端配置等 以前的都是spring security oauth默认的token生成策略,token默认在org.springframe ...

  8. XMind *思维导图的安装步骤(图文详解)

    不多说,直接上干货! XMind中文官网:  http://www.xmindchina.net/ 这一款软件,是非常实用和棒,也帮助我了很多地方.推荐给大家 需要正版和激活的,请见博文最下端的QQ技 ...

  9. zabbix邮件内容乱码与邮件内容为附件解决办法

    在zabbix的实际使用过程中,在收到邮件预警的时候,我们会发现邮件内容是乱码的,在手机端收到的是附件,而且附件下载后的文件类型是打不开的.这样我们不知道我们是哪个服务器的哪项服务出了问题,接下来我们 ...

  10. WPF将TextBox的边框设为圆角的

    将TextBox的边框设为圆角的,因为TextBox默认的样式中边框就是由Border类型来实现的, 所以只需要真的当前的TextBox的Border修改属性即可,为了不影响界面中别的Border的样 ...