项目开发--------XMPP即时通讯
生活随笔
收集整理的這篇文章主要介紹了
项目开发--------XMPP即时通讯
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
一.基本框架結(jié)構(gòu):
?
StroyBoard的基本頁面搭建:
?
?
?
二.個功能代碼塊的是實(shí)現(xiàn)
?
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 ---實(shí)現(xiàn)XMPPStreamDelegate中的代理方法//認(rèn)證登錄成功的代理方法 -(void)xmppStreamDidAuthenticate:(XMPPStream *)sender {NSLog(@"登錄成功");//登陸成功進(jìn)入好友聊天頁面 [self dismissViewControllerAnimated:YES completion:nil];} //認(rèn)證登錄失敗的代理方法 -(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 設(shè)置代理監(jiān)測注冊是否成功 [[XMPPManager sharedXMPPManager].stream addDelegate:self delegateQueue:dispatch_get_main_queue()]; }#pragma mark ---實(shí)現(xiàn)XMPPStreamDelegate中的代理方法//注冊成功 -(void)xmppStreamDidRegister:(XMPPStream *)sender {NSLog(@"注冊成功");//注冊成功 進(jìn)入登陸頁面 [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文件 (主要功能實(shí)現(xiàn)文件)
?
XMPPManager.m文件(主要功能實(shí)現(xiàn)文件)
#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; //用來表示訪問服務(wù)器的目的(登錄或注冊) @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方法,是為了創(chuàng)建 通道(xmppStream) //init方法 - (instancetype)init {self = [super init];if (self) {//初始化通道self.stream = [[XMPPStream alloc] init];//指定其連接的服務(wù)器IP地址self.stream.hostName = kHostName;//指定服務(wù)器端口 默認(rèn)為5222//端口號 是制定當(dāng)前連接的是什么服務(wù)self.stream.hostPort = kHostPort;//給stream設(shè)置代理,來檢測鏈接狀態(tài)和認(rèn)證狀態(tài) [self.stream addDelegate:self delegateQueue:dispatch_get_main_queue()];//初始化管理好友對象roster(與好友相關(guān)的操作)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;//此時將枚舉屬性的值設(shè)為connectToSeverLoginself.connectPurpose = connectToSeverLogin;//鏈接 [self linkConnect];}//鏈接的方法 -(void)linkConnect {//在真正鏈接之前,需要告訴服務(wù)器你是誰,//XMPPJID在Xmpp中身份的唯一標(biāo)識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設(shè)置到Stream通道上self.stream.myJID = myJID;//開始鏈接if ([self.stream isConnected] || [self.stream isConnecting]) {//先斷開 [self disconnectToSever];}//連接到服務(wù)器NSError *error = nil;[self.stream connectWithTimeout:30.0 error:&error];if (error) {NSLog(@"error:%@",error);}}//斷開鏈接 -(void)disconnectToSever{//設(shè)置下線狀態(tài)元素XMPPPresence *pressence = [XMPPPresence presenceWithType:@"unavailable"];//將stream上的狀態(tài)改為下線 [self.stream sendElement:pressence];//斷開鏈接 [self.stream disconnect];}#pragma mark ---注冊 -(void)registerWithUserName:(NSString *)userName passWord:(NSString *)passWord {self.registerPassWord = passWord;self.registerUserName = userName;//將枚舉值設(shè)為注冊self.connectPurpose = connectToSeverRegister;//鏈接 [self linkConnect]; }#pragma mark ---XMPPStreamDelegate的方法 //鏈接成功 -(void)xmppStreamDidConnect:(XMPPStream *)sender {NSLog(@"連接成功");//進(jìn)行認(rèn)證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(@"鏈接超時");} //認(rèn)證成功 -(void)xmppStreamDidAuthenticate:(XMPPStream *)sender {NSLog(@"認(rèn)證成功");//設(shè)置上線狀態(tài)XMPPPresence *presence = [XMPPPresence presenceWithType:@"available"];[self.stream sendElement:presence];}#pragma mark ---刪除好友 -(void)removeFriendName:(NSString *)name {//根據(jù)username和域名,創(chuàng)建一個jidXMPPJID *friendJid = [XMPPJID jidWithString:[NSString stringWithFormat:@"%@@%@",name,kDomin ]];//取消對好友的監(jiān)聽 [self.roster unsubscribePresenceFromUser:friendJid];//將好友移除 [self.roster removeUser:friendJid];}@end
?
?
?RosterTableViewController.m文件(好友界面功能的實(shí)現(xiàn))
#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];//對數(shù)組進(jìn)行初始化self.allRoster = [NSMutableArray array];//通過代理協(xié)議,獲取好友 [[XMPPManager sharedXMPPManager].roster addDelegate:self delegateQueue:dispatch_get_main_queue()];//監(jiān)聽好友的狀態(tài) 通過代理協(xié)議的形式 [[XMPPManager sharedXMPPManager].stream addDelegate:self delegateQueue:dispatch_get_main_queue()];}#pragma mark ---實(shí)現(xiàn)XMPPRosterDelegate協(xié)議中的方法 //開始獲取好友 -(void)xmppRosterDidBeginPopulating:(XMPPRoster *)sender {NSLog(@"開始獲取好友");} //正在獲取好友 有幾個好友這個放法就會執(zhí)行幾次 -(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];//如果之前加過了,表示好友已經(jīng)存在if ([_allRoster containsObject:frienfJid ]) {return;}//將好友對象(frienfJid) 添加到數(shù)組中 [self.allRoster addObject:frienfJid];//插入行//插入到最后一行NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self.allRoster.count - 1 inSection:0];[self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];}}//結(jié)束獲取好友 -(void)xmppRosterDidEndPopulating:(XMPPRoster *)sender {NSLog(@"好友獲取結(jié)束"); }//獲取好友請求 -(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://點(diǎn)擊拒絕按鈕 [[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 --實(shí)現(xiàn)XMPPStreamDelegate中的方法 //監(jiān)聽好友的狀態(tài) -(void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence {//監(jiān)測好友的狀態(tài)NSString *presenceType = presence.type;if ([presenceType isEqualToString:@"available"]) {NSLog(@"好友在線狀態(tài)!");} else if ([presenceType isEqualToString:@"unavailable"])NSLog(@"好友處于下線狀態(tài)!");}#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) {//刪除數(shù)據(jù)源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 {//獲取點(diǎn)擊的cellUITableViewCell *cell = (UITableViewCell *)sender;NSIndexPath *indexPah = [self.tableView indexPathForCell:cell];ChatTableViewController *chatVC = (ChatTableViewController *)segue.destinationViewController;chatVC.chatToJid = _allRoster[indexPah.row];}@end?
ChatTableViewController.h文件(聊天界面功能的實(shí)現(xiàn))
?
#import <UIKit/UIKit.h> #import "XMPPManager.h"@interface ChatTableViewController : UITableViewController@property(nonatomic,strong)XMPPJID *chatToJid;@end?
?ChatTableViewController.m文件(聊天界面功能的實(shí)現(xiàn))
#import "ChatTableViewController.h" #import "XMPPManager.h"@interface ChatTableViewController ()<XMPPStreamDelegate>//信息數(shù)組 @property(nonatomic,strong)NSMutableArray *allMessages; - (IBAction)sendMessage:(UIBarButtonItem *)sender;@end@implementation ChatTableViewController- (void)viewDidLoad {[super viewDidLoad];//初始化數(shù)組self.allMessages = [NSMutableArray array];//設(shè)置代理 [[XMPPManager sharedXMPPManager].stream addDelegate:self delegateQueue:dispatch_get_main_queue()];//顯示歷史記錄 [self parseMesage];}#pragma mark --實(shí)現(xiàn)協(xié)議中的方法 //已經(jīng)接受好友發(fā)送的信息 -(void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message {NSLog(@"已經(jīng)接受信息:%@",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) { //自己發(fā)的cell.detailTextLabel.text = message.body;cell.textLabel.text = @"";} else {cell.textLabel.text = message.body;cell.detailTextLabel.text = @"";}return cell; }#pragma mark --給好友發(fā)送消息 - (IBAction)sendMessage:(UIBarButtonItem *)sender {//發(fā)送給誰消息(Jid)XMPPMessage *message = [XMPPMessage messageWithType:@"chat" to:self.chatToJid];//設(shè)置發(fā)送內(nèi)容[message addBody:@"你好!"];//開始發(fā)送 [[XMPPManager sharedXMPPManager].stream sendElement:message];} //信息發(fā)送成功 -(void)xmppStream:(XMPPStream *)sender didSendMessage:(XMPPMessage *)message {NSLog(@"信息發(fā)送成功:%@",message);[self parseMesage];} //信息發(fā)送失敗 -(void)xmppStream:(XMPPStream *)sender didFailToSendMessage:(XMPPMessage *)message error:(NSError *)error {NSLog(@"信息發(fā)送失敗:%@",error);}@end?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/erdeng/p/4951143.html
總結(jié)
以上是生活随笔為你收集整理的项目开发--------XMPP即时通讯的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [实战]MVC5+EF6+MySql企业
- 下一篇: SQLSERVER自动定时(手动)备份工