Xmpp (即时通讯)

//首先要配置好环境,Xampp / openfire /spark
XmppManager.h文件
#import <Foundation/Foundation.h> #import "XMPPFramework.h" @protocol XmppManagerDelegate<NSObject> - (void)jumpPage; @end @interface XmppManager : NSObject<XMPPStreamDelegate> //建立通信管道 @property(nonatomic,strong)XMPPStream * xmppStream; //设置代理属性 @property(nonatomic,assign)id<XmppManagerDelegate>delegate; //好友列表(花名册) @property(nonatomic,strong)XMPPRoster * roster; @property(nonatomic,strong)XMPPMessageArchiving *xmppMessageArchiving;//消息归档 @property(nonatomic,strong)NSManagedObjectContext *messageContext;//管理上下文对象 //单例 + (instancetype)shareXmppManager; //注册用户 - (void)registerWithUserName:(NSString *)userName PassWord:(NSString*)passWord; //登陆 - (void)loginWithUserName :(NSString *)userName PassWord:(NSString *)passWord; @end
XmppManager.m
#import "XmppManager.h"
#import <UIKit/UIKit.h>
typedef NS_ENUM(NSInteger, ConncetToServerpopurse) {
ConnectToServerpopurseLogin,//登陆
ConnectToServerpopurseRegister//注册
};
@interface XmppManager ()<XMPPRosterDelegate,UIAlertViewDelegate>
//连接服务器的目的
@property(nonatomic,assign)ConncetToServerpopurse conncetpopurse;
@property(nonatomic,copy)NSString * loginPassword;//登陆密码
@property(nonatomic,copy)NSString * registerPassword;//注册密码
@property(nonatomic,strong)XMPPJID * formJid;//接收jid;
@end
@implementation XmppManager
#pragma mark----单例
+ (instancetype)shareXmppManager{
static XmppManager * manager=nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
manager =[[XmppManager alloc]init];
});
return manager;
}
-(instancetype)init{
self =[super init];
if (self) {
//通信管道初始化
self.xmppStream =[[XMPPStream alloc]init];
//服务器名称 域名
self.xmppStream.hostName =kHostName;
//端口号
self.xmppStream.hostPort =kHostPort;
//添加代理
[self.xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
//创建管理助手
XMPPRosterCoreDataStorage *rosterStorage =[XMPPRosterCoreDataStorage sharedInstance];
//初始化花名册
self.roster =[[XMPPRoster alloc]initWithRosterStorage:rosterStorage dispatchQueue:dispatch_get_main_queue()];
//设置代理
[self.roster addDelegate:self delegateQueue:dispatch_get_main_queue()];
//激活通信管道
[self.roster activate:self.xmppStream];
//初始化消息归档
XMPPMessageArchivingCoreDataStorage * coredataStorage =[XMPPMessageArchivingCoreDataStorage sharedInstance];
self.xmppMessageArchiving =[[XMPPMessageArchiving alloc]initWithMessageArchivingStorage:coredataStorage dispatchQueue:dispatch_get_main_queue()];
//设置代理
[self.xmppMessageArchiving addDelegate:self delegateQueue:dispatch_get_main_queue()
];
//激活通信管道
[self.xmppMessageArchiving activate:self.xmppStream];
self.messageContext =coredataStorage.mainThreadManagedObjectContext;
}
return self;
}
#pragma mark---注册
- (void)registerWithUserName:(NSString *)userName PassWord:(NSString *)passWord{
self.conncetpopurse=ConnectToServerpopurseRegister;
self.registerPassword=passWord;
[self createMyJid:userName];
}
#pragma mark ---登陆
- (void)loginWithUserName:(NSString *)userName PassWord:(NSString *)passWord{
self.loginPassword=passWord;
self.conncetpopurse=ConnectToServerpopurseLogin;
[self createMyJid:userName];
}
//创建myJid
- (void)createMyJid:(NSString *)userName {
//创建地址 XMPPJID
XMPPJID * myJid =[XMPPJID jidWithUser:userName domain:kDomin resource:kResource];
self.xmppStream.myJID =myJid;
[self connectServer];
}
//连接服务器
- (void)connectServer {
//连接服务器
//判断是否连接
if ([self.xmppStream isConnected]) {
//断开连接
[self.xmppStream disconnect];
//下线
XMPPPresence * presence =[XMPPPresence presenceWithType:@"unavailabel"];
//发送
[self.xmppStream sendElement:presence];
}
//没有连接的话 直接建立连接
[self.xmppStream connectWithTimeout:30.f error:nil];
}
#pragma mark---xmppStream协议方法
#pragma mark------连接成功
-(void)xmppStreamDidConnect:(XMPPStream *)sender{
NSLog(@"function==%s, line==%d",__FUNCTION__,__LINE__);
switch (self.conncetpopurse) {
case 0:
//登陆
[self.xmppStream authenticateWithPassword:self.loginPassword error:nil];
break;
case 1:
//注册
[self.xmppStream registerWithPassword:self.registerPassword error:nil];
break;
default:
break;
}
}
#pragma mark -----连接失败
-(void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error{
NSLog(@"function==%s, line==%d",__FUNCTION__,__LINE__);
}
#pragma mark----连接超时
-(void)xmppStreamConnectDidTimeout:(XMPPStream *)sender{
NSLog(@"function==%s, line==%d",__FUNCTION__,__LINE__);
}
#pragma mark----注册成功
-(void)xmppStreamDidRegister:(XMPPStream *)sender{
NSLog(@"function==%s, line==%d",__FUNCTION__,__LINE__);
}
#pragma mark-----注册失败
-(void)xmppStream:(XMPPStream *)sender didNotRegister:(DDXMLElement *)error{
NSLog(@"function==%s, line==%d",__FUNCTION__,__LINE__);
}
#pragma mark-------用户名验证成功
-(void)xmppStreamDidAuthenticate:(XMPPStream *)sender{
NSLog(@"function==%s, line==%d",__FUNCTION__,__LINE__);
XMPPPresence * prence =[XMPPPresence presenceWithType:@"availabel"];
[self.xmppStream sendElement:prence];
[self.delegate jumpPage];
}
#pragma mark--------用户名验证失败
-(void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error{
[self.delegate jumpPage];
NSLog(@"function==%s, line==%d",__FUNCTION__,__LINE__);
}
//xmppRosterDelegate协议的方法
#pragma mark ----接收到好友请求
-(void)xmppRoster:(XMPPRoster *)sender didReceivePresenceSubscriptionRequest:(XMPPPresence *)presence{
self.formJid =presence.from;
UIAlertView *alert =[[UIAlertView alloc]initWithTitle:@"好友请求" message:@"是否同意好友请求" delegate:self cancelButtonTitle:@"同意" otherButtonTitles:@"拒绝", nil];
[alert show];
}
//UIAlertViewDelegate方法
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSLog(@"function==%s, line==%d",__FUNCTION__,__LINE__);
switch (buttonIndex) {
case 0:
//同意请求
[self.roster acceptPresenceSubscriptionRequestFrom:self.formJid andAddToRoster:YES];
break;
case 1:
//拒绝好友请求
[self.roster rejectPresenceSubscriptionRequestFrom:self.formJid];
break;
default:
break;
}
}
@end
//登陆界面
#import "LoginViewController.h"
#import "XmppManager.h"
#import "RosterTableViewController.h"
@interface LoginViewController ()<XmppManagerDelegate>
@property (strong, nonatomic) IBOutlet UITextField *userName;
@property (strong, nonatomic) IBOutlet UITextField *password;
- (IBAction)loginAction:(UIButton *)sender;
- (IBAction)registerAction:(UIButton *)sender;
@end
@implementation LoginViewController
- (void)viewDidLoad {
[super viewDidLoad];
[XmppManager shareXmppManager].delegate =self;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
//登陆
- (IBAction)loginAction:(UIButton *)sender {
[[XmppManager shareXmppManager] loginWithUserName:self.userName.text PassWord:self.password.text];
}
//注册
- (IBAction)registerAction:(UIButton *)sender {
}
//实现xmppManagerDelegate代理方法
- (void)jumpPage{
if ([[XmppManager shareXmppManager].xmppStream isAuthenticated]) {
RosterTableViewController * roster =[[RosterTableViewController alloc]init];
[self.navigationController pushViewController:roster animated:YES];
}else{
UIAlertView * alert =[[UIAlertView alloc]initWithTitle:@"提示" message:@"用户名或者密码错误" delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
[alert show];
}
}
@end
//注册界面
#import "RegisterViewController.h"
#import "XmppManager.h"
@interface RegisterViewController ()
- (IBAction)registerButton:(UIButton *)sender;
- (IBAction)backAction:(UIBarButtonItem *)sender;
@property (strong, nonatomic) IBOutlet UITextField *userName;
@property (strong, nonatomic) IBOutlet UITextField *passWord;
@end
@implementation RegisterViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
//注册
- (IBAction)registerButton:(UIButton *)sender {
[[XmppManager shareXmppManager]registerWithUserName:self.userName.text PassWord:self.passWord.text];
[self dismissViewControllerAnimated:YES completion:nil];
}
//返回
- (IBAction)backAction:(UIBarButtonItem *)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
@end
//好友列表
#import "RosterTableViewController.h"
#import "ChatTableViewController.h"
#import "XmppManager.h"
@interface RosterTableViewController ()<XMPPRosterDelegate>
@property(nonatomic,strong)NSMutableArray * rosterArray;//存放好友
@end
@implementation RosterTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
//注册
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"rosterCell"];
[[XmppManager shareXmppManager].roster addDelegate:self delegateQueue:dispatch_get_main_queue()];
self.navigationItem.title=@"好友列表";
}
#pragma mark----开始检索
-(void)xmppRosterDidBeginPopulating:(XMPPRoster *)sender{
NSLog(@"function==%s, line==%d",__FUNCTION__,__LINE__);
NSLog(@"开始检索");
}
#pragma mark ---结束检索
-(void)xmppRosterDidEndPopulating:(XMPPRoster *)sender{
NSLog(@"function==%s, line==%d",__FUNCTION__,__LINE__);
NSLog(@"结束检索");
}
#pragma mark-----获取到好友
//每次获取一个
-(void)xmppRoster:(XMPPRoster *)sender didReceiveRosterItem:(DDXMLElement *)item{
NSString * userName =[[item attributeForName:@"jid"]stringValue];
//拿到一个好友的jid
XMPPJID * rosterJid =[XMPPJID jidWithString:userName resource:kResource];
//判断是否添加过
if ([self.rosterArray containsObject:rosterJid]) {
return ;
}else{
[self.rosterArray addObject:rosterJid];
}
//获取indexpath
NSIndexPath * indexPath =[NSIndexPath indexPathForRow:self.rosterArray.count-1 inSection:0];
[self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationLeft];
[self.tableView reloadData];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.rosterArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"rosterCell" forIndexPath:indexPath];
XMPPJID *jid =self.rosterArray[indexPath.row];
cell.textLabel.text=jid.user;
return cell;
}
//懒加载
-(NSMutableArray *)rosterArray{
if (!_rosterArray) {
self.rosterArray =[NSMutableArray array];
}
return _rosterArray;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
ChatTableViewController * chatVC=[[ChatTableViewController alloc]init];
//向聊天界面传聊天对象的jid
XMPPJID *chatToJid =self.rosterArray[indexPath.row];
chatVC.chatToJid =chatToJid;
[self.navigationController pushViewController:chatVC animated:YES];
}
消息界面.h文件
#import <UIKit/UIKit.h> #import "XMPPFramework.h" #import "XmppManager.h" @interface ChatTableViewController : UITableViewController<XMPPStreamDelegate> @property(nonatomic,strong)XMPPJID * chatToJid;//聊天对象的jid @property(nonatomic,strong)NSManagedObjectContext * messageContext;//管理对象上下文 @end
消息界面.m文件
#import "ChatTableViewController.h"
@interface ChatTableViewController ()
@property(nonatomic,strong)NSMutableArray *messageArray;//接收消息的数组
@end
@implementation ChatTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title =@"消息";
//注册
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"chatCell"];
//添加通信管道代理
[[XmppManager shareXmppManager].xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
UIBarButtonItem * rightBt=[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(sendmessages)];
self.navigationItem.rightBarButtonItem =rightBt;
self.messageContext =[XmppManager shareXmppManager].messageContext;
}
//发送消息按钮
- (void)sendmessages{
//创建消息
XMPPMessage * xmppMessage =[[XMPPMessage alloc]initWithType:@"chat" to:self.chatToJid ];
//发送消息
[xmppMessage addBody:@"研发26"];
[[XmppManager shareXmppManager].xmppStream sendElement:xmppMessage];
}
#pragma mark -----消息接收成功
-(void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message{
//刷新界面
[self reloadMessage];
}
#pragma mark------消息发送成功
-(void)xmppStream:(XMPPStream *)sender didSendMessage:(XMPPMessage *)message{
//刷新界面
[self reloadMessage];
}
//刷新界面
- (void)reloadMessage{
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"XMPPMessageArchiving_Message_CoreDataObject" inManagedObjectContext:self.messageContext];
[fetchRequest setEntity:entity];
// Specify criteria for filtering which objects to fetch
XMPPStream * stream =[XmppManager shareXmppManager].xmppStream;
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"streamBareJidStr =%@ AND bareJidStr = %@",stream.myJID.bare, self.chatToJid.bare];
[fetchRequest setPredicate:predicate];
// Specify how the fetched objects should be sorted
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"timestamp"
ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObjects:sortDescriptor, nil]];
NSError *error = nil;
NSArray *fetchedObjects = [self.messageContext executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects == nil) {
return;
}
if (self.messageArray.count !=0) {
[self.messageArray removeAllObjects];
}
[self.messageArray addObjectsFromArray:fetchedObjects];
[self.tableView reloadData];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.messageArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"chatCell" forIndexPath:indexPath];
if (!cell) {
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"chatCell"];
}
cell.detailTextLabel.textAlignment =NSTextAlignmentLeft;
XMPPMessageArchiving_Message_CoreDataObject *messageCordata =self.messageArray[indexPath.row];
if (messageCordata.isOutgoing) {
//消息是我发
cell.detailTextLabel.hidden =YES;
cell.textLabel.hidden=NO;
cell.textLabel.text =messageCordata.body;
}else{
cell.textLabel.hidden=YES;
cell.detailTextLabel.hidden=NO;
cell.detailTextLabel.text=messageCordata.body;
}
return cell;
}
//懒加载
-(NSMutableArray *)messageArray{
if (!_messageArray) {
self.messageArray =[NSMutableArray array];
}
return _messageArray;
}

浙公网安备 33010602011771号