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.mapp

#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

 

//登錄界面dom

#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

 //註冊界面fetch

#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

 

//好友列表atom

#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文件spa

#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;
}
相關文章
相關標籤/搜索