IOS XMPP(即時通信的框架)

 

#import "AppDelegate.h"
#import "XMPPFramework.h"
/* * 在AppDelegate實現登陸 1. 初始化XMPPStream 2. 鏈接到服務器[傳一個JID] 3. 鏈接到服務成功後,再發送密碼受權 4. 受權成功後,發送"在線" 消息 */
@interface AppDelegate ()<XMPPStreamDelegate>{ XMPPStream *_xmppStream; } // 1. 初始化XMPPStream
-(void)setupXMPPStream; // 2.鏈接到服務器
-(void)connectToHost; // 3.鏈接到服務成功後,再發送密碼受權
-(void)sendPwdToHost; // 4.受權成功後,發送"在線" 消息
-(void)sendOnlineToHost; @end

@implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // 程序一啓動就鏈接到主機
 [self connectToHost]; return YES; } #pragma mark  -私有方法
#pragma mark 初始化XMPPStream
-(void)setupXMPPStream{ _xmppStream = [[XMPPStream alloc] init]; // 設置代理
    [_xmppStream addDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)]; } #pragma mark 鏈接到服務器
-(void)connectToHost{ NSLog(@"開始鏈接到服務器"); if (!_xmppStream) { [self setupXMPPStream]; } // 設置登陸用戶JID //resource 標識用戶登陸的客戶端 iphone android
 XMPPJID *myJID = [XMPPJID jidWithUser:@"wangwu" domain:@"teacher.local" resource:@"iphone" ]; _xmppStream.myJID = myJID; // 設置服務器域名
    _xmppStream.hostName = @"teacher.local";//不只能夠是域名,還但是IP地址 // 設置端口 若是服務器端口是5222,能夠省略
    _xmppStream.hostPort = 5222; // 鏈接
    NSError *err = nil; if(![_xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:&err]){ NSLog(@"%@",err); } } #pragma mark 鏈接到服務成功後,再發送密碼受權
-(void)sendPwdToHost{ NSLog(@"再發送密碼受權"); NSError *err = nil; [_xmppStream authenticateWithPassword:@"123456" error:&err]; if (err) { NSLog(@"%@",err); } } #pragma mark  受權成功後,發送"在線" 消息
-(void)sendOnlineToHost{ NSLog(@"發送 在線 消息"); XMPPPresence *presence = [XMPPPresence presence]; NSLog(@"%@",presence); [_xmppStream sendElement:presence]; } #pragma mark -XMPPStream的代理
#pragma mark 與主機鏈接成功
-(void)xmppStreamDidConnect:(XMPPStream *)sender{ NSLog(@"與主機鏈接成功"); // 主機鏈接成功後,發送密碼進行受權
 [self sendPwdToHost]; } #pragma mark  與主機斷開鏈接
-(void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error{ // 若是有錯誤,表明鏈接失敗
    NSLog(@"與主機斷開鏈接 %@",error); } #pragma mark 受權成功
-(void)xmppStreamDidAuthenticate:(XMPPStream *)sender{ NSLog(@"受權成功"); [self sendOnlineToHost]; } #pragma mark 受權失敗
-(void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error{ NSLog(@"受權失敗 %@",error); } #pragma mark -公共方法
-(void)logout{ // 1." 發送 "離線" 消息"
    XMPPPresence *offline = [XMPPPresence presenceWithType:@"unavailable"]; [_xmppStream sendElement:offline]; // 2. 與服務器斷開鏈接
 [_xmppStream disconnect]; } @end

 

           封裝好的XMPP工具(登陸,註冊,註銷)  android

            WCXMPPTool.h服務器

#import <Foundation/Foundation.h>
#import "Singleton.h"
#import "XMPPFramework.h"


typedef enum {
    XMPPResultTypeLoginSuccess,//登陸成功
    XMPPResultTypeLoginFailure,//登陸失敗
    XMPPResultTypeNetErr,//網絡不給力
    XMPPResultTypeRegisterSuccess,//註冊成功
    XMPPResultTypeRegisterFailure//註冊失敗
}XMPPResultType;

typedef void (^XMPPResultBlock)(XMPPResultType type);// XMPP請求結果的block

@interface WCXMPPTool : NSObject

singleton_interface(WCXMPPTool);


@property (nonatomic, strong)XMPPvCardTempModule *vCard;//電子名片

/**
 *  註冊標識 YES 註冊 / NO 登陸
 */
@property (nonatomic, assign,getter=isRegisterOperation) BOOL  registerOperation;//註冊操做

/**
 *  用戶註銷
 
 */
-(void)xmppUserlogout;
/**
 *  用戶登陸
 */
-(void)xmppUserLogin:(XMPPResultBlock)resultBlock;


/**
 *  用戶註冊
 */
-(void)xmppUserRegister:(XMPPResultBlock)resultBlock;
@end
View Code

           WCXMPPTool.m網絡

#import "WCXMPPTool.h"


/*
 * 在AppDelegate實現登陸
 
 1. 初始化XMPPStream
 2. 鏈接到服務器[傳一個JID]
 3. 鏈接到服務成功後,再發送密碼受權
 4. 受權成功後,發送"在線" 消息
 */
@interface WCXMPPTool ()<XMPPStreamDelegate>{
    XMPPStream *_xmppStream;
    XMPPResultBlock _resultBlock;
    
    
    XMPPvCardCoreDataStorage *_vCardStorage;//電子名片的數據存儲
    
    XMPPvCardAvatarModule *_avatar;//頭像模塊
}

// 1. 初始化XMPPStream
-(void)setupXMPPStream;


// 2.鏈接到服務器
-(void)connectToHost;

// 3.鏈接到服務成功後,再發送密碼受權
-(void)sendPwdToHost;


// 4.受權成功後,發送"在線" 消息
-(void)sendOnlineToHost;
@end


@implementation WCXMPPTool


singleton_implementation(WCXMPPTool)



#pragma mark  -私有方法
#pragma mark 初始化XMPPStream
-(void)setupXMPPStream{
    
    _xmppStream = [[XMPPStream alloc] init];
    
#warning 每個模塊添加後都要激活
    //添加電子名片模塊
    _vCardStorage = [XMPPvCardCoreDataStorage sharedInstance];
    _vCard = [[XMPPvCardTempModule alloc] initWithvCardStorage:_vCardStorage];
    
    //激活
    [_vCard activate:_xmppStream];
    
    //添加頭像模塊
    _avatar = [[XMPPvCardAvatarModule alloc] initWithvCardTempModule:_vCard];
    [_avatar activate:_xmppStream];
    

    // 設置代理
    [_xmppStream addDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];
}

#pragma mark 鏈接到服務器
-(void)connectToHost{
    WCLog(@"開始鏈接到服務器");
    if (!_xmppStream) {
        [self setupXMPPStream];
    }
    
    
    // 設置登陸用戶JID
    //resource 標識用戶登陸的客戶端 iphone android
    
    // 從單例獲取用戶名
    NSString *user = nil;
    if (self.isRegisterOperation) {
        user = [WCUserInfo sharedWCUserInfo].registerUser;
    }else{
        user = [WCUserInfo sharedWCUserInfo].user;
    }
    
    XMPPJID *myJID = [XMPPJID jidWithUser:user domain:@"teacher.local" resource:@"iphone" ];
    _xmppStream.myJID = myJID;
    
    // 設置服務器域名
    _xmppStream.hostName = @"127.0.0.1";//不只能夠是域名,還但是IP地址
    
    // 設置端口 若是服務器端口是5222,能夠省略
    _xmppStream.hostPort = 5222;
    
    // 鏈接
    NSError *err = nil;
    if(![_xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:&err]){
        WCLog(@"%@",err);
    }
    
}


#pragma mark 鏈接到服務成功後,再發送密碼受權
-(void)sendPwdToHost{
    WCLog(@"再發送密碼受權");
    NSError *err = nil;
    
    // 從單例裏獲取密碼
    NSString *pwd = [WCUserInfo sharedWCUserInfo].pwd;
    
    [_xmppStream authenticateWithPassword:pwd error:&err];
    
    if (err) {
        WCLog(@"%@",err);
    }
}

#pragma mark  受權成功後,發送"在線" 消息
-(void)sendOnlineToHost{
    
    WCLog(@"發送 在線 消息");
    XMPPPresence *presence = [XMPPPresence presence];
    WCLog(@"%@",presence);
    
    [_xmppStream sendElement:presence];
    
    
}
#pragma mark -XMPPStream的代理
#pragma mark 與主機鏈接成功
-(void)xmppStreamDidConnect:(XMPPStream *)sender{
    WCLog(@"與主機鏈接成功");
    
    if (self.isRegisterOperation) {//註冊操做,發送註冊的密碼
        NSString *pwd = [WCUserInfo sharedWCUserInfo].registerPwd;
        [_xmppStream registerWithPassword:pwd error:nil];
    }else{//登陸操做
        // 主機鏈接成功後,發送密碼進行受權
        [self sendPwdToHost];
    }
    
}
#pragma mark  與主機斷開鏈接
-(void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error{
    // 若是有錯誤,表明鏈接失敗
    
    // 若是沒有錯誤,表示正常的斷開鏈接(人爲斷開鏈接)
    
    
    if(error && _resultBlock){
        _resultBlock(XMPPResultTypeNetErr);
    }
    WCLog(@"與主機斷開鏈接 %@",error);
    
}


#pragma mark 受權成功
-(void)xmppStreamDidAuthenticate:(XMPPStream *)sender{
    WCLog(@"受權成功");
    
    [self sendOnlineToHost];
    
    // 回調控制器登陸成功
    if(_resultBlock){
        _resultBlock(XMPPResultTypeLoginSuccess);
    }
    
    
}


#pragma mark 受權失敗
-(void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error{
    WCLog(@"受權失敗 %@",error);
    
    // 判斷block有無值,再回調給登陸控制器
    if (_resultBlock) {
        _resultBlock(XMPPResultTypeLoginFailure);
    }
}

#pragma mark 註冊成功
-(void)xmppStreamDidRegister:(XMPPStream *)sender{
    WCLog(@"註冊成功");
    if(_resultBlock){
        _resultBlock(XMPPResultTypeRegisterSuccess);
    }
    
}

#pragma mark 註冊失敗
-(void)xmppStream:(XMPPStream *)sender didNotRegister:(DDXMLElement *)error{
    
    WCLog(@"註冊失敗 %@",error);
    if(_resultBlock){
        _resultBlock(XMPPResultTypeRegisterFailure);
    }
    
}

#pragma mark -公共方法
-(void)xmppUserlogout{
    // 1." 發送 "離線" 消息"
    XMPPPresence *offline = [XMPPPresence presenceWithType:@"unavailable"];
    [_xmppStream sendElement:offline];
    
    // 2. 與服務器斷開鏈接
    [_xmppStream disconnect];
    
    // 3. 回到登陸界面
    //    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Login" bundle:nil];
    //
    //    self.window.rootViewController = storyboard.instantiateInitialViewController;
    [UIStoryboard showInitialVCWithName:@"Login"];
    
    
    //4.更新用戶的登陸狀態
    [WCUserInfo sharedWCUserInfo].loginStatus = NO;
    [[WCUserInfo sharedWCUserInfo] saveUserInfoToSanbox];
    
}

-(void)xmppUserLogin:(XMPPResultBlock)resultBlock{
    
    // 先把block存起來
    _resultBlock = resultBlock;
    
    //    Domain=XMPPStreamErrorDomain Code=1 "Attempting to connect while already connected or connecting." UserInfo=0x7fd86bf06700 {NSLocalizedDescription=Attempting to connect while already connected or connecting.}
    // 若是之前鏈接過服務,要斷開
    [_xmppStream disconnect];
    
    // 鏈接主機 成功後發送登陸密碼
    [self connectToHost];
}


-(void)xmppUserRegister:(XMPPResultBlock)resultBlock{
    // 先把block存起來
    _resultBlock = resultBlock;
    
    // 若是之前鏈接過服務,要斷開
    [_xmppStream disconnect];
    
    // 鏈接主機 成功後發送註冊密碼
    [self connectToHost];
}

@end
View Code

 

          自動登陸app

          AppDelegate.m      dom

#import "AppDelegate.h"
#import "XMPPFramework.h"
#import "WCNavigationController.h"
#import "DDLog.h"
#import "DDTTYLogger.h"

@implementation AppDelegate




- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    //從沙盒的路徑
    NSString *path=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject];
    
    //打開XMPP的日誌
    [DDLog addLogger:[DDTTYLogger sharedInstance]];
    

    //設置導航欄背景
  //  [WCNavigationController setupNavTheme];
    
    //從沙盒裏加載用戶的數據單例
    [[WCUserInfo sharedWCUserInfo] loadUserInfoFromSanbox];
    
    //判斷用戶的登陸狀態,YES直接來到主界面
    if([WCUserInfo sharedWCUserInfo].loginStatus){
        UIStoryboard *storayobard=[UIStoryboard storyboardWithName:@"Main" bundle:nil];
        self.window.rootViewController=storayobard.instantiateInitialViewController;
        
        //自動登陸服務
        [[WCXMPPTool sharedWCXMPPTool]xmppUserLogin:nil];
    }
    
    return YES;
}
@end
View Code

         

          登陸方法iphone

#import "WCBaseLoginViewController.h"
#import "AppDelegate.h"

@implementation WCBaseLoginViewController


- (void)login{
    // 登陸
    
    /*
     * 官方的登陸實現
     
     * 1.把用戶名和密碼放在WCUserInfo的單例
     
     
     * 2.調用 AppDelegate的一個login 鏈接服務並登陸
     */
    
    //隱藏鍵盤
    [self.view endEditing:YES];
    
    // 登陸以前給個提示
    
    [MBProgressHUD showMessage:@"正在登陸中..." toView:self.view];
    
    [WCXMPPTool sharedWCXMPPTool].registerOperation = NO;
    __weak typeof(self) selfVc = self;
    
    [[WCXMPPTool sharedWCXMPPTool] xmppUserLogin:^(XMPPResultType type) {
        [selfVc handleResultType:type];
    }];
}


-(void)handleResultType:(XMPPResultType)type{
    // 主線程刷新UI
    dispatch_async(dispatch_get_main_queue(), ^{
        [MBProgressHUD hideHUDForView:self.view
         ];
        switch (type) {
            case XMPPResultTypeLoginSuccess:
                NSLog(@"登陸成功");
                [self enterMainPage];
                break;
            case XMPPResultTypeLoginFailure:
                NSLog(@"登陸失敗");
                [MBProgressHUD showError:@"用戶名或者密碼不正確" toView:self.view];
                break;
            case XMPPResultTypeNetErr:
                [MBProgressHUD showError:@"網絡不給力" toView:self.view];
            default:
                break;
        }
    });
    
}


-(void)enterMainPage{
    
    // 更改用戶的登陸狀態爲YES
    [WCUserInfo sharedWCUserInfo].loginStatus = YES;
    
    // 把用戶登陸成功的數據,保存到沙盒
    [[WCUserInfo sharedWCUserInfo] saveUserInfoToSanbox];
    
    // 隱藏模態窗口
    [self dismissViewControllerAnimated:NO completion:nil];
    
    // 登陸成功來到主界面
    // 此方法是在子線程補調用,因此在主線程刷新UI
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    self.view.window.rootViewController = storyboard.instantiateInitialViewController;
}
View Code
相關文章
相關標籤/搜索