• 新.XMPP用户登录及注册


    一、新建两个storyboard。一个用于实现用户登录及注册,一个负责实现即时通讯主体功能。

    在主控制器的storyboard中拖入Tab Bar controller控制器 删除两个分支

    再拖入几个Navigation Controller控制器

    Tab Bar controllerView controllers连线到对应的Navigation Controller控制器

    Navigation Controller控制器的子视图Table View控制器上>修改title标题。

    将图片文件夹拖入images.xcassets中。点击Navigation Controller控制器按钮 在右侧修改Bar item名称及图片。

    拖入图标时,记录勾选App icon 中的iphone ios6ios7支持。

    按钮背影拉伸,show slicing最低支持7.0,如果使用了不想用,得把slicing 选项改成None

    二、

    storyboard中拖入一个View视图到界面(可以方便屏幕适配),再往视图上拖入buttonText添加ToolCategory文件夹

    1.输入框需要用户使用回车键  就需要将输入框的delegate属性连线到控制器,再到文件中继承<UITextFieldDelegate>

    -(void)textFieldShouldReturn:(UITextField *)textField{//监听文本输入方法

      if (textField ==_userNameText){

      [_passwordText becomeFirstResponder];

      }else{

      //登录

      [self userLogin];

      }

      return YES;

    }

    2.1.将登录连接方法 -(IBAction)userLogin;

    在方法中{

      1.检查用户输入是否完整

      //截断字符串前后的空格(密码除外),从而可以最大程度降低用户输入错误

      NSString *userName = [_userNametext.text trimString]; 

     NSString *password = _passwordText.text;   //有些用户会使用空格做密码 

      if ([userName isEmptyString] || [password isEmptyString]){  //判断用户信息是否输入完整

      UIAlertView *alter = [[UIAlertView alloc] initWithTitle:@"提示" message:@"登录信息不完整" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil,nil];

      [alter show];

      // 2. 将用户登录信息写入系统偏好

    [[LoginUsersharedLoginUser] setUserName:userName];

    [[LoginUsersharedLoginUser] setPassword:password];

    [[LoginUsersharedLoginUser] setHostName:hostName];

    // 3. AppDelegate开始连接

    // 告诉AppDelegate,当前是注册用户

    NSString *errorMessage = nil;

    if (button.tag == 1) {

    [selfappDelegate].isRegisterUser = YES;

    errorMessage = @"注册用户失败!";

    } else {

    errorMessage = @"用户登录失败!";

    }

    [[selfappDelegate] connectWithCompletion:nilfailed:^{

    UIAlertView *alter = [[UIAlertViewalloc] initWithTitle:@"提示"message:errorMessage delegate:nilcancelButtonTitle:@"确定"otherButtonTitles:nil, nil];

    [alter show];

    if (button.tag == 1) {

    // 注册用户失败通常是因为用户名重复

    [_userNameTextbecomeFirstResponder];

    } else {

    // 登录失败通常是密码输入错误

    [_passwordTextsetText:@""];

    [_passwordTextbecomeFirstResponder];

    }

    }];


      return;

      }

    2.2.AppDelegate开始连接、添加AppDelegate.h头文件

     添加 -(AppDelegate *)appDelegate{ //并初始化这个方法

        return [[UIApplication sharedApplication] delegate];

        }

    2.3.viewDidLoad中添加拉伸按钮图片

    // 1) 登录按钮

    UIImage *loginImage = [UIImageimageNamed:@"LoginGreenBigBtn"];

    loginImage = [loginImage stretchableImageWithLeftCapWidth:loginImage.size.width * 0.5topCapHeight:loginImage.size.height * 0.5];


    相对上面布局:选中两个要对齐的元素,点击.Editor>pin>Vertical Spacing



    2.4AppDelegate.m文件中

    interface中新建方法:遵守XMPPStreamDelegate协议可以方便编写代码(不写也可以)

      1.设置XMPPStream>setupStream

      2.通知服务器用户上线>goOnline

      3.通知服务器用户下线>goOffline

      4.连接到服务器>connect

      5.与服务器断开连接>disConnect

    并实现。

    3.//设置setupStream实例化流。

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

    这个方法中// 2. 设置XMPPStream并调用[selfsetupStream];

    。在.h头文件中定义XMPP相关的属性的方法定义> 全局的XMPPStream,只读属性readonly

    {

    这里可以使用断言,就可以不用判断xmppStream是否为nil,等于nil才实例化。

    // 0. 方法被调用时,要求_xmppStream必须为nil,否则通过断言提示程序员,并终止程序运行!

    NSAssert(_xmppStream == nil, @"XMPPStream被多次实例化!");


      1.实例化流

      _xmppStream [[XMPPStream alloc] init];

      


     // 2 设置重新连接模块,需要在XMPPStream文件中打开XMPPReconnect文件

    ,实例化,激活就可以使用了。在代理中添加成员变量XMPPReconnect *_xmppReconnect;

    _xmppReconnect = [[XMPPReconnect alloc] init];

      // 3将重新连接模块添加到XMPPStream

    [_xmppReconnect activate:_xmppStream];

     // 4.添加代理。因为所有网络请求都是做基于网络的数据处理,跟 UI无关,因此可以让代理yyifd其化线程中 ,从而提高程序的运行性能

      [_xmppStream addDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)];


    }

    4.//注销已注册的扩展模块。当内存不足或注销的时候 销毁XMPPStream并注销已注册的扩展模块

    - (void)teardownStream

    {

    // 1.删除代理

    [_xmppStream removeDelegate:self];

     

    // 2. 取消激活在setupStream方法中激活的扩展模块

    [_xmppReconnectdeactivate];

    // 3. 断开XMPPStream的连接

    [_xmppStreamdisconnect];

     

    // 4. 内存清理

    _xmppStream = nil;

    _xmppReconnect = nil;

    }

    5.- (void)dealloc

    {

    // 释放XMPP相关对象及扩展模块

    [self teardownStream];

    }

    //通知服务器用户上线

    6.goOnline{

      //1。实例化一个上线报告,默认类型为:available

      XMPPPresence *presence = [XMPPPressence presence];

      [_xmppStream sendElement:presence];  //这个方法没有回调,只通知我的好友

    }

    7.goOffline{

      //1.实例化一个下线报告

        XMPPPresence *presence = [XMPPPresence presenceWithType:@"unavailable"];

      //2.发送presence给服务器,通知服务器客户端下线

        [_xmppStream sendElement:presence];

    }

    8.保持用户登录信息

    AppDelegate.h文件中 定义一个连接到服务器的方法 判断是否正确失败块代

    typedef void(^CompletionBlock)();


    -(void)connectWithUserName:(CompletionBlock *)completion password:(CompletionBlock *)faild; //completion 正确块代码 faild错误块代码方法新建一个类LoginUser.封装一个单独的类来保持用户登录信息

    .h文件中添加Singleton.h头文件在@interface定义属性

    single_interface(LoginUser)

    @property (strong, nonatomic) NSString *userName;

    @property (strong, nonatomic) NSString *password;

    @property (strong, nonatomic) NSString *

    @property (strong, nonatomic, readonly) NSString *myJIDName;

    hostName;

    再到.m文件中定义single_implementation(LoginUser)和导入NSString+Helper.h头文件

    以及定义#用户名,密码,服务器

    #define kXMPPUserNameKey    @"xmppUserName"

          #define kXMPPPasswordKey    @"xmppPassword"

          #define kXMPPHostNameKey    @"xmppHostName"

    实现方法

      - (NSString *)loadStringFromDefaultsWithKey:(NSString *)key

      {

    NSString *str = [[NSUserDefaults standardUserDefaults] stringForKey:key]; 

    return (str) ? str : @"";

      }

      - (NSString *)userName

      { return [self loadStringFromDefaultsWithKey:kXMPPUserNameKey];}


      - (void)setUserName:(NSString *)userName

      { [userName saveToNSDefaultsWithKey:kXMPPUserNameKey];}


      - (NSString *)password

      {return [self loadStringFromDefaultsWithKey:kXMPPPasswordKey];}


      - (void)setPassword:(NSString *)password

      { [password saveToNSDefaultsWithKey:kXMPPPasswordKey];}


      - (NSString *)hostName

      { return [self loadStringFromDefaultsWithKey:kXMPPHostNameKey];}


      - (void)setHostName:(NSString *)hostName

      { [hostName saveToNSDefaultsWithKey:kXMPPHostNameKey];}


    - (NSString *)myJIDName

    { return [NSStringstringWithFormat:@"%@@%@", self.userName, self.hostName];

    }



    9.连接connnect.在代理. m文件导入保持用户登录信息LoginUser头文件

    // 1. 如果XMPPStream当前已经连接,直接返回 就不会需调用”[self setupStream];“

    if ([_xmppStreamisConnected]) { return; }

    // 2. 指定用户名、主机(服务器),连接时不需要password

    NSString *hostName = [[LoginUsersharedLoginUser] hostName];

    NSString *userName = [[LoginUsersharedLoginUser] myJIDName];

    // 3. 设置XMPPStreamJID和主机

    [_xmppStreamsetMyJID:[XMPPJIDjidWithString:userName]];

    [_xmppStreamsetHostName:hostName];

    // 4. 开始连接

    NSError *error = nil;

    [_xmppStreamconnectWithTimeout:XMPPStreamTimeoutNoneerror:&error];

    // 提示:如果没有指定JIDhostName,才会出错,其他都不出错。

    if (error) {

    NSLog(@"连接请求发送出错 - %@", error.localizedDescription);

    } else {

    NSLog(@"连接请求发送成功!");

    }

    }

    //断开连接

    desConnect{

      //通知服务器下线

      [self goOffline];

      //XMPPStream断开连接

      [_xmppStream disconnect];

    }



    #pragma mark – 代理方法

    .h文件中,定义方法是否注册用户标示

    @property (assign, nonatomic) BOOL isRegisterUser;

    @property ( assign,nonatomic) BOOL isUserLogon;

    .m 文件中继续追加成员变量:

    CompletionBlock _completionBlock; // 成功的块代码

    CompletionBlock _faildBlock; // 失败的块代码



    #pragma mark 连接完成(如果服务器地址不对,就不会调用此方法)

    - (void)xmppStreamDidConnect:(XMPPStream *)sender

    {

    // 从系统偏好读取用户密码

    NSString *password = [[LoginUsersharedLoginUser] password];

    if (_isRegisterUser) {

    // 用户注册,发送注册请求

    [_xmppStreamregisterWithPassword:password error:nil];

    } else {

    // 用户登录,发送身份验证请求

    [_xmppStreamauthenticateWithPassword:password error:nil];

    }

    }


    #pragma mark 注册成功

    - (void)xmppStreamDidRegister:(XMPPStream *)sender

    {

    _isRegisterUser = NO;

    // 注册成功,直接发送验证身份请求,从而触发后续的操作

    [_xmppStreamauthenticateWithPassword:[LoginUsersharedLoginUser].passworderror:nil];

    }


    #pragma mark 注册失败(用户名已经存在)

    - (void)xmppStream:(XMPPStream *)sender didNotRegister:(DDXMLElement *)error

    {

    _isRegisterUser = NO;

    if (_faildBlock != nil) {

    dispatch_async(dispatch_get_main_queue(), ^{

    _faildBlock();

    });

    }

    }


    #pragma mark 身份验证通过

    - (void)xmppStreamDidAuthenticate:(XMPPStream *)sender

    {

    if (_completionBlock != nil) {

    dispatch_async(dispatch_get_main_queue(), ^{

    _completionBlock();

    });

    }

    // 通知服务器用户上线

    [selfgoOnline];

    // 显示主Storyboard

    [selfshowStoryboardWithLogonState:YES];

    }


    定义头文件#define kNotificationUserLogonState @"NotificationUserLogon"

    .m文件中

    #pragma mark 根据用户登录状态加载对应的Storyboard显示

    - (void)showStoryboardWithLogonState:(BOOL)isUserLogon

    {

    UIStoryboard *storyboard = nil;

    if (isUserLogon) {

    // 显示Main.storyboard

    storyboard = [UIStoryboardstoryboardWithName:@"Main"bundle:nil];

    } else {

    // 显示Login.sotryboard

    storyboard = [UIStoryboardstoryboardWithName:@"Login"bundle:nil];

    }

    // 在主线程队列负责切换Storyboard,而不影响后台代理的数据处理

    dispatch_async(dispatch_get_main_queue(), ^{

    // 如果在项目属性中,没有指定主界面(启动的Storyboardself.window不会被实例化)

    // Storyboard的初始视图控制器设置为windowrootViewController

    [self.windowsetRootViewController:storyboard.instantiateInitialViewController];

    if (!self.window.isKeyWindow) {

    [self.windowmakeKeyAndVisible];

    }

    });

    }



    #pragma mark 密码错误,身份验证失败

    - (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error

    {

    if (_faildBlock != nil) {

    dispatch_async(dispatch_get_main_queue(), ^{

    _faildBlock();

    });

    }

    // 显示用户登录Storyboard

    [selfshowStoryboardWithLogonState:NO];

    }


    - (void)applicationDidBecomeActive:(UIApplication *)application

    {

    // 应用程序被激活后,直接连接,使用系统偏好中的保存的用户记录登录

    // 从而实现自动登录的效果!

    [selfconnect];

    }

    - (void)applicationWillResignActive:(UIApplication *)application

    {

    [selfdisconnect];

    }


    添加一个注销按钮,退出到登录界面

    新建一个UITableViewController控制器。选择Table View控制器连线到点M文件中。


    在该方法中。添加AppDelegate.h头文件并在代理头文件写入注册方法。

    在代理.M文件中实现方法{

    // 1. 通知服务器下线,并断开连接

    [selfdisconnect];

    // 2. 显示用户登录Storyboard

    [selfshowStoryboardWithLogonState:NO];


    logout方法中 设置_isUserLogon = No;

    在注销文件中,初始化AppDelegate方法

    在注销按钮中调用[self appDelegate] logout];就能实现注销用户登录了


    ----------------



  • 相关阅读:
    JAVA日报
    JAVA日报
    JAVA日报
    JAVA
    leetcode刷题笔记 222题 完全二叉树的节点个数
    leetcode刷题笔记 221题 最大正方形
    leetcode刷题笔记 220题 存在重复元素 III
    leetcode刷题笔记 219题 存在重复元素 II
    leetcode刷题笔记 218题 天际线问题
    leetcode刷题笔记 216题 组合总和 III
  • 原文地址:https://www.cnblogs.com/qq907374866/p/4253513.html
Copyright © 2020-2023  润新知