zoukankan      html  css  js  c++  java
  • ESFramework Demo之iPhone版登录(续)

      上一回我们只是画了一个界面,虽然我们看到了用于输入昵称和密码的文本框,但我们还没有给这两个文本框做输入键盘的订制。本文接着上篇,把后续的功能完成,其内容包括根据登陆协议构造byte流,发送给Server.解析Server返回的登录结果,判断登陆是否成功,如果成功,由登录界面跳转到聊天主界面,如图:

      1.为登录界面的文本框订制键盘,比如说,现在比较流行的登录多数是用信箱作为登录的用户名的,那上图的键盘中就没有@这个按键,一会我们就做一个有@的。上图的是为password订制的键盘它有一个Done键,点它就可以发送登录请求。下面是实现的代码:

                          昵称的

        ((CellWithTextField *)cell).txt.clearButtonMode = UITextFieldViewModeWhileEditing;

        ((CellWithTextField *)cell).txt.keyboardType = UIKeyboardTypeEmailAddress;

        ((CellWithTextField *)cell).txt.autocorrectionType = UITextAutocorrectionTypeNo;

        ((CellWithTextField *)cell).txt.autocapitalizationType = UITextAutocapitalizationTypeNone;

        ((CellWithTextField *)cell).txt.returnKeyType = UIReturnKeyNext;

        ((CellWithTextField *)cell).txt.tag = 1;

        ((CellWithTextField *)cell).txt.delegate = self;

                          密码的

        ((CellWithTextField *)cell).txt.clearButtonMode = UITextFieldViewModeWhileEditing;

        ((CellWithTextField *)cell).txt.secureTextEntry = YES;

        ((CellWithTextField *)cell).txt.autocorrectionType = UITextAutocorrectionTypeNo;

        ((CellWithTextField *)cell).txt.autocapitalizationType = UITextAutocapitalizationTypeNone;

        ((CellWithTextField *)cell).txt.returnKeyType = UIReturnKeyDone;

        ((CellWithTextField *)cell).txt.tag = 2;

        ((CellWithTextField *)cell).txt.delegate = self;


        这里有一个delegate = self,有用到协议这个知识点,简单的说一下objective-c中的协议是为了让两个类实现通信。如此处的UITextField,无论它的returnKeyType是Done还是Next,做为呈载它的容器RootViewController是要为它实现特定的业务处理的,RootViewController就要实现这个协议所定义的方法。这是在RootViewController.h中的 @interface RootViewController : UITableViewController<UITextFieldDelegate>说明RootViewController要实现UITextFieldDelegate协议中的方法,本例中的方法是-(BOOL)textFieldShouldReturn:(UITextField*)field, 由此方法我们可以对不同的UITextField对象做不同的处理代码如下:


        -(BOOL)textFieldShouldReturn:(UITextField*)field

        {

          if (field.tag == 1) {

            //NSLog(@"昵称");

            [field resignFirstResponder];

            [(UITextField *)[self.view viewWithTag:2] becomeFirstResponder];

          } else{

             //NSLog(@"");

             //如果是框点击的Done那我们在此处要加入构造登录请求的byte流

          }

        }

      2.按登录协议构造byet流


        messageData = [NSMutableData data];

        Login *loginBody = [[Login alloc] init];

        loginBody.password = [(UITextField *)[self.view viewWithTag:2] text];

        loginBody.passwordLen = [loginBody.password length];

        unsigned short startToken = 0xFFFF;

        [messageData appendBytes:&startToken length:sizeof(startToken)];

        //录协议的messageType116,些处我们用了硬编码,以后要改用常量 

        unsigned short messageType = 116

        [self addUnsignedShort:messageType];

        int messageID = 1;

        [self addInt:messageID];

        unsigned char tempChar = 0;

        if ([loginBody.password isEqualToString:@""]) {

          loginBody.passwordLen = 8;

        }

        int messageBodyLen = 4 + loginBody.passwordLen; // int 4

        [self addInt:messageBodyLen];

        NSString *userID = [(UITextField *)[self.view viewWithTag:1] text];

        unsigned char userIDLen = ([userID length]<=11)?[userID length]:11;

        [self addUnsignedChar:userIDLen];

        if (userIDLen<11) {

          [messageData appendData:[userID dataUsingEncoding:NSUTF8StringEncoding]];

          for (int i=0;i<11-userIDLen;i++) {

            [self addUnsignedChar:tempChar];

          }

        }

        else {

          [messageData appendData:[userID dataUsingEncoding:NSUTF8StringEncoding]];

        }

        NSString *destUserID = @"_0";

        unsigned char destUserIDLen = ([destUserID length]<=11)?[destUserID length]:11;

        [self addUnsignedChar:destUserIDLen];

        [messageData appendData:[destUserID dataUsingEncoding:NSUTF8StringEncoding]];

        for (int i=0;i<9;i++) {

          [self addUnsignedChar:tempChar];

        }

        [self addInt:loginBody.passwordLen];

        if ([loginBody.password isEqualToString:@""]) {

          for (int i=0; i<8; i++) {

            [self addUnsignedChar:tempChar];

          }

        }

        else {

          if (loginBody.passwordLen<8) {

            [messageData appendData:[loginBody.password dataUsingEncoding:NSUTF8StringEncoding]];

            for (int i=0; i<8-loginBody.passwordLen; i++) {

              [self addUnsignedChar:tempChar];

            }

          }

          else {

            [messageData appendData:[loginBody.password dataUsingEncoding:NSUTF8StringEncoding]];

          }

        }

        这具体的登录协议在IPhone和ESFramework通信的Demo中有详细的讲解请看此处 


       3.构造socket向Server发消息

               ClientSocket * mysocket = [ClientSocket client];

         [mysocket sendData:messageData];


        这里我们用了单件模式构造出socket 调动它的sendData方法,把我们的messageData中的byte流发给Server


       4.处理收到的消息

             一量我们发给Server的登录请求被处理了,那么Server就会返回我们一个登录结果,用来告诉我们是登录成功了还是失败了,在ClientSocket.m中实现如下:

        //获取后的信息处理

        - (void) processData:(NSData*)data{

           NSLog(@"ClientSocket::processData data is: %@", data);

           //messageType

           unsigned short messageType;

           [data getBytes:&messageType range:NSMakeRange(2, 2)];

           //NSLog(@"ClientSocket::processData messageType is: %d ",messageType);

           int messageBodyLen;

           [data getBytes:&messageBodyLen range:NSMakeRange(8, 4)];

           //NSLog(@"ClientSocket::processData messageBodyLen is: %d ",messageBodyLen);

           int logonResult;

           switch (messageType) {

             case 116:                

             [data getBytes:&logonResult range:NSMakeRange(40, 4)];

             if (logonResult==0) {

               NSLog(@"录成功");

               RapidEngineDemoAppDelegate* appData = [[UIApplication sharedApplication] delegate];

               [appData loginSuccess];

             }

             else {

               NSLog(@"录失败");

             }

             break;

               default:

             break;

           }

        }

       5.登录成功后跳转页面

             在RapidEngineDemoAppDelegate.m中的方法-(void)loginSuccess 

        -(void)loginSuccess{

          [window bringSubviewToFront:chatTabController.view];

        }

            使预先定义好的chatTabController显示出来,OK到此我们的登录处理就算完成了,Client和Server不只是建立了连接,还彼此发了消息,我很开心啊,但在真正的应用中Server还是要实时感知Client是否还存在,有没有掉线,这就要靠心跳消息了,通过Client与Server互通心跳来更好的维持它们之间的有效通信,我们还要把协议分成消息头和消息体分别处理,具体实现请看下篇,本例中的源码可以点此处下载,多谢          

  • 相关阅读:
    进制
    enum
    文件操作fstream
    文件读取 FILE
    static_cast、dynamic_cast、reinterpret_cast、和const_c
    std::max 错误
    boost 时间
    c++ new 和delete
    c++ static静态
    BOOST 之filesystem, path
  • 原文地址:https://www.cnblogs.com/upwifi/p/2155532.html
Copyright © 2011-2022 走看看