• 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工具(登录,注册,注销)  

                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

              自动登录

              AppDelegate.m     

    #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

             

              登录方法

    #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
  • 相关阅读:
    Ural 2070:Interesting Numbers(思维)
    Codeforces 760B:Frodo and pillows(二分)
    Codeforces 760C:Pavel and barbecue(DFS+思维)
    Codeforces 730I:Olympiad in Programming and Sports(最小费用流)
    HDU-2102 A计划
    HDU-2181 哈密顿绕行世界问题
    HDU-1226 超级密码
    学习系列
    学习系列
    学习系列
  • 原文地址:https://www.cnblogs.com/liuwj/p/6978013.html
Copyright © 2020-2023  润新知