700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 项目开发--------XMPP即时通讯

项目开发--------XMPP即时通讯

时间:2018-11-09 09:41:59

相关推荐

项目开发--------XMPP即时通讯

一.基本框架结构:

StroyBoard的基本页面搭建:

二.个功能代码块的是实现

LoginViewController.m文件(登录页面的基本配置)

#import "LoginViewController.h"#import "XMPPManager.h"@interface LoginViewController ()<XMPPStreamDelegate>@property (weak, nonatomic) IBOutlet UITextField *userNameTes;@property (weak, nonatomic) IBOutlet UITextField *passwordTes;@end@implementation LoginViewController- (void)viewDidLoad {[super viewDidLoad];//添加代理方法 [[XMPPManager sharedXMPPManager].stream addDelegate:self delegateQueue:dispatch_get_main_queue()]; }#pragma mark ---实现XMPPStreamDelegate中的代理方法

//认证登录成功的代理方法-(void)xmppStreamDidAuthenticate:(XMPPStream *)sender{NSLog(@"登录成功");//登陆成功进入好友聊天页面 [self dismissViewControllerAnimated:YES completion:nil];}//认证登录失败的代理方法-(void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error{NSLog(@"登录失败%@",error);}- (IBAction)loginWithUserNameAndPassword:(id)sender {//登录 [[XMPPManager sharedXMPPManager] loginWithUserName:self.userNameTes.text passWord:self.passwordTes.text];}@end

RegisterViewController.m文(注册页面的基本配置)

#import "RegisterViewController.h"#import "XMPPManager.h"@interface RegisterViewController () <XMPPStreamDelegate>@property (weak, nonatomic) IBOutlet UITextField *userNameTes;@property (weak, nonatomic) IBOutlet UITextField *passwordTes;@end@implementation RegisterViewController- (void)viewDidLoad {[super viewDidLoad];//给stream 设置代理监测注册是否成功 [[XMPPManager sharedXMPPManager].stream addDelegate:self delegateQueue:dispatch_get_main_queue()];}#pragma mark ---实现XMPPStreamDelegate中的代理方法

//注册成功-(void)xmppStreamDidRegister:(XMPPStream *)sender{NSLog(@"注册成功");//注册成功 进入登陆页面 [self.navigationController popViewControllerAnimated:YES];}//注册失败-(void)xmppStream:(XMPPStream *)sender didNotRegister:(DDXMLElement *)error{NSLog(@"注册失败");}- (IBAction)registerWithUserNameAndPassword:(id)sender {//注册[[XMPPManager sharedXMPPManager] registerWithUserName:self.userNameTes.text passWord:self.passwordTes.text];}@end

XMPPManager.h文件 (主要功能实现文件)

#import <Foundation/Foundation.h>#import "XMPPFramework.h"@interface XMPPManager : NSObject<XMPPStreamDelegate>//声明一个'通道'属性 为了其他类中能够访问到@property(nonatomic,strong)XMPPStream *stream;//与好友有关的操作@property(nonatomic,strong)XMPPRoster *roster;//与聊天信息有关的 聊天信息托管上下文@property(nonatomic,strong)NSManagedObjectContext *context;//信息归档 聊天信息归档对象@property(nonatomic,strong)XMPPMessageArchiving *messageAchiving;#pragma mark ---获取一个单例对象+(XMPPManager *)sharedXMPPManager;#pragma mark ---登录-(void)loginWithUserName:(NSString *)userName passWord:(NSString *)passWord;#pragma mark ---注册-(void)registerWithUserName:(NSString *)userName passWord:(NSString *)passWord;#pragma mark ---删除好友-(void)removeFriendName:(NSString *)name;@end

XMPPManager.m文件(主要功能实现文件)

#import "XMPPManager.h"

//枚举typedef NS_ENUM(NSUInteger,connectToSeverType){connectToSeverLogin,connectToSeverRegister};//枚举//typedef enum : NSUInteger {// <#MyEnumValueA#>,// <#MyEnumValueB#>,// <#MyEnumValueC#>,//} <#MyEnum#>;@interface XMPPManager ()//登录用户名@property(nonatomic,strong)NSString *LoginuserName;//登录密码@property(nonatomic,strong)NSString *loginPassWord;//注册名@property(nonatomic,strong)NSString *registerUserName;//注册密码@property(nonatomic,strong)NSString *registerPassWord;//用来表示访问服务器的目的(登录或注册)@property(nonatomic,assign)connectToSeverType connectPurpose;@end@implementation XMPPManager#pragma mark ---获取一个单例对象+(XMPPManager *)sharedXMPPManager{static XMPPManager *manager = nil;static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{manager = [[XMPPManager alloc] init];});return manager;}//重写XMPPManager的init方法,是为了创建 通道(xmppStream)//init方法- (instancetype)init{self = [super init];if (self) {//初始化通道self.stream = [[XMPPStream alloc] init];//指定其连接的服务器IP地址self.stream.hostName = kHostName;//指定服务器端口 默认为5222//端口号 是制定当前连接的是什么服务self.stream.hostPort = kHostPort;//给stream设置代理,来检测链接状态和认证状态 [self.stream addDelegate:self delegateQueue:dispatch_get_main_queue()];//初始化管理好友对象roster(与好友相关的操作)XMPPRosterCoreDataStorage *storage = [XMPPRosterCoreDataStorage sharedInstance];self.roster = [[XMPPRoster alloc] initWithRosterStorage:storage dispatchQueue:dispatch_get_main_queue()];//在管道上激活对象 [self.roster activate:self.stream];//初始化messageAchiving对象XMPPMessageArchivingCoreDataStorage *messageStroge = [XMPPMessageArchivingCoreDataStorage sharedInstance];self.messageAchiving = [[XMPPMessageArchiving alloc] initWithMessageArchivingStorage:messageStroge dispatchQueue:dispatch_get_main_queue()];//激活 [self.messageAchiving activate:self.stream];//托管上下文对象self.context = messageStroge.mainThreadManagedObjectContext;}return self;}#pragma mark ---登录-(void)loginWithUserName:(NSString *)userName passWord:(NSString *)passWord{self.loginPassWord = userName;self.LoginuserName = userName;//此时将枚举属性的值设为connectToSeverLoginself.connectPurpose = connectToSeverLogin;//链接 [self linkConnect];}//链接的方法-(void)linkConnect{//在真正链接之前,需要告诉服务器你是谁,//XMPPJID在Xmpp中身份的唯一标识XMPPJID *myJID = nil;switch (self.connectPurpose) {case connectToSeverLogin:{myJID = [XMPPJID jidWithUser:self.LoginuserName domain:kDomin resource:kResource];break;}case connectToSeverRegister:{myJID = [XMPPJID jidWithUser:self.registerUserName domain:kDomin resource:kResource];break;}default:break;}// XMPPJID *myJID = [XMPPJID jidWithUser:self.LoginuserName domain:kDomin resource:kResource];//将自己的JID设置到Stream通道上self.stream.myJID = myJID;//开始链接if ([self.stream isConnected] || [self.stream isConnecting]) {//先断开 [self disconnectToSever];}//连接到服务器NSError *error = nil;[self.stream connectWithTimeout:30.0 error:&error];if (error) {NSLog(@"error:%@",error);}}//断开链接-(void)disconnectToSever{//设置下线状态元素XMPPPresence *pressence = [XMPPPresence presenceWithType:@"unavailable"];//将stream上的状态改为下线 [self.stream sendElement:pressence];//断开链接 [self.stream disconnect];}#pragma mark ---注册-(void)registerWithUserName:(NSString *)userName passWord:(NSString *)passWord{self.registerPassWord = passWord;self.registerUserName = userName;//将枚举值设为注册self.connectPurpose = connectToSeverRegister;//链接 [self linkConnect];}#pragma mark ---XMPPStreamDelegate的方法//链接成功-(void)xmppStreamDidConnect:(XMPPStream *)sender{NSLog(@"连接成功");//进行认证switch (self.connectPurpose) {case connectToSeverLogin://如果链接的目的是登录,这里需要一个登录的passWord [self.stream authenticateWithPassword:self.loginPassWord error:nil];break;case connectToSeverRegister://如果链接的目的是注册,这里需要一个注册的passWord [self.stream registerWithPassword:self.registerPassWord error:nil];break;default:break;}}//链接失败-(void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error{NSLog(@"连接失败%@",error);}//链接超时-(void)xmppStreamConnectDidTimeout:(XMPPStream *)sender{NSLog(@"链接超时");}//认证成功-(void)xmppStreamDidAuthenticate:(XMPPStream *)sender{NSLog(@"认证成功");//设置上线状态XMPPPresence *presence = [XMPPPresence presenceWithType:@"available"];[self.stream sendElement:presence];}#pragma mark ---删除好友-(void)removeFriendName:(NSString *)name{//根据username和域名,创建一个jidXMPPJID *friendJid = [XMPPJID jidWithString:[NSString stringWithFormat:@"%@@%@",name,kDomin ]];//取消对好友的监听 [self.roster unsubscribePresenceFromUser:friendJid];//将好友移除 [self.roster removeUser:friendJid];}@end

RosterTableViewController.m文件(好友界面功能的实现)

#import "RosterTableViewController.h"#import "XMPPManager.h"#import "ChatTableViewController.h"@interface RosterTableViewController ()<XMPPRosterDelegate,UIAlertViewDelegate,XMPPStreamDelegate>//所有好友@property(nonatomic,strong)NSMutableArray *allRoster;//请求者的jid@property(nonatomic,strong)XMPPJID *requestJid;@end//存放所有的好友@implementation RosterTableViewController- (void)viewDidLoad {[super viewDidLoad];//对数组进行初始化self.allRoster = [NSMutableArray array];//通过代理协议,获取好友 [[XMPPManager sharedXMPPManager].roster addDelegate:self delegateQueue:dispatch_get_main_queue()];//监听好友的状态 通过代理协议的形式 [[XMPPManager sharedXMPPManager].stream addDelegate:self delegateQueue:dispatch_get_main_queue()];}#pragma mark ---实现XMPPRosterDelegate协议中的方法//开始获取好友-(void)xmppRosterDidBeginPopulating:(XMPPRoster *)sender{NSLog(@"开始获取好友");}//正在获取好友 有几个好友这个放法就会执行几次-(void)xmppRoster:(XMPPRoster *)sender didReceiveRosterItem:(DDXMLElement *)item{NSLog(@"%@",item);//to 订阅了别人//from 别人订阅了你//both 互为好友NSString *subscription = [[item attributeForName:@"subscription"] stringValue];if ([subscription isEqualToString:@"from"] || [subscription isEqualToString:@"both"]) {//获取好友的jid字符串NSString *jidStr = [[item attributeForName:@"jid" ] stringValue];//获取好友的jidXMPPJID *frienfJid = [XMPPJID jidWithString:jidStr];//如果之前加过了,表示好友已经存在if ([_allRoster containsObject:frienfJid ]) {return;}//将好友对象(frienfJid) 添加到数组中 [self.allRoster addObject:frienfJid];//插入行//插入到最后一行NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self.allRoster.count - 1 inSection:0];[self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];}}//结束获取好友-(void)xmppRosterDidEndPopulating:(XMPPRoster *)sender{NSLog(@"好友获取结束");}//获取好友请求-(void)xmppRoster:(XMPPRoster *)sender didReceivePresenceSubscriptionRequest:(XMPPPresence *)presence{NSLog(@"获取好友请求!");self.requestJid = presence.from;UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"好友请求" message:_requestJid.user delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil];[alert show];}-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{switch (buttonIndex) {case 0://点击拒绝按钮[[XMPPManager sharedXMPPManager].roster rejectPresenceSubscriptionRequestFrom:self.requestJid];break;case 1://接受请求按钮 [[XMPPManager sharedXMPPManager].roster acceptPresenceSubscriptionRequestFrom:self.requestJid andAddToRoster:NO];break;default:break;}self.requestJid = nil;}#pragma mark --实现XMPPStreamDelegate中的方法//监听好友的状态-(void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence{//监测好友的状态NSString *presenceType = presence.type;if ([presenceType isEqualToString:@"available"]) {NSLog(@"好友在线状态!");} else if ([presenceType isEqualToString:@"unavailable"])NSLog(@"好友处于下线状态!");}#pragma mark - Table view data source- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {// Return the number of sections.return 1;}- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {// Return the number of rows in the section.return self.allRoster.count;}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"roster" forIndexPath:indexPath];XMPPJID *friendJid = _allRoster[indexPath.row];cell.textLabel.text = friendJid.user;return cell;}// Override to support conditional editing of the table view.- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {// Return NO if you do not want the specified item to be editable.return YES;}// Override to support editing the table view.- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {if (editingStyle == UITableViewCellEditingStyleDelete) {//删除数据源XMPPJID *jid = _allRoster[indexPath.row];[[XMPPManager sharedXMPPManager]removeFriendName:jid.user];[self.allRoster removeObjectAtIndex:indexPath.row];[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];} else if (editingStyle == UITableViewCellEditingStyleInsert) {// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view } }#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 {//获取点击的cellUITableViewCell *cell = (UITableViewCell *)sender;NSIndexPath *indexPah = [self.tableView indexPathForCell:cell];ChatTableViewController *chatVC = (ChatTableViewController *)segue.destinationViewController;chatVC.chatToJid = _allRoster[indexPah.row];}@end

ChatTableViewController.h文件(聊天界面功能的实现)

#import <UIKit/UIKit.h>#import "XMPPManager.h"@interface ChatTableViewController : UITableViewController@property(nonatomic,strong)XMPPJID *chatToJid;@end

ChatTableViewController.m文件(聊天界面功能的实现)

#import "ChatTableViewController.h"#import "XMPPManager.h"@interface ChatTableViewController ()<XMPPStreamDelegate>//信息数组@property(nonatomic,strong)NSMutableArray *allMessages;- (IBAction)sendMessage:(UIBarButtonItem *)sender;@end@implementation ChatTableViewController- (void)viewDidLoad {[super viewDidLoad];//初始化数组self.allMessages = [NSMutableArray array];//设置代理 [[XMPPManager sharedXMPPManager].stream addDelegate:self delegateQueue:dispatch_get_main_queue()];//显示历史记录 [self parseMesage];}#pragma mark --实现协议中的方法//已经接受好友发送的信息-(void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message{NSLog(@"已经接受信息:%@",message);[self parseMesage];}-(void)parseMesage{//查询请求NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];NSEntityDescription *entity = [NSEntityDescription entityForName:@"XMPPMessageArchiving_Message_CoreDataObject" inManagedObjectContext:[XMPPManager sharedXMPPManager].context];[fetchRequest setEntity:entity];// Specify criteria for filtering which objects to fetch//谓词 查询条件NSPredicate *predicate = [NSPredicate predicateWithFormat:@"bareJidStr == %@ AND streamBareJidStr == %@", _chatToJid.bare,[XMPPManager sharedXMPPManager].stream.myJID.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 = [[XMPPManager sharedXMPPManager].context executeFetchRequest:fetchRequest error:&error];if (fetchedObjects == nil) {NSLog(@"没有聊天记录!");} else {//清空之前的聊天记录 [self.allMessages removeAllObjects];[self.allMessages addObjectsFromArray:fetchedObjects];[self.tableView reloadData];if (_allMessages.count == 0) {return;}NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self.allMessages.count -1 inSection:0];[self.tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionBottom];}}#pragma mark - Table view data source- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {#warning Incomplete implementation, return the number of sectionsreturn 1;}- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {#warning Incomplete implementation, return the number of rowsreturn _allMessages.count;}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"chat" forIndexPath:indexPath];XMPPMessageArchiving_Message_CoreDataObject *message = _allMessages[indexPath.row];if (message.isOutgoing == YES) { //自己发的cell.detailTextLabel.text = message.body;cell.textLabel.text = @"";} else {cell.textLabel.text = message.body;cell.detailTextLabel.text = @"";}return cell;}#pragma mark --给好友发送消息- (IBAction)sendMessage:(UIBarButtonItem *)sender {//发送给谁消息(Jid)XMPPMessage *message = [XMPPMessage messageWithType:@"chat" to:self.chatToJid];//设置发送内容[message addBody:@"你好!"];//开始发送 [[XMPPManager sharedXMPPManager].stream sendElement:message];}//信息发送成功-(void)xmppStream:(XMPPStream *)sender didSendMessage:(XMPPMessage *)message{NSLog(@"信息发送成功:%@",message);[self parseMesage];}//信息发送失败-(void)xmppStream:(XMPPStream *)sender didFailToSendMessage:(XMPPMessage *)message error:(NSError *)error{NSLog(@"信息发送失败:%@",error);}@end

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。
相关阅读
xmpp即时通讯原理

xmpp即时通讯原理

2018-10-03

即时通讯:XMPP基础

即时通讯:XMPP基础

2022-08-04

xmpp即时通讯二

xmpp即时通讯二

2023-04-10

XMPP - 即时通讯技术

XMPP - 即时通讯技术

2020-11-25