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互通心跳来更好的维持它们之间的有效通信,我们还要把协议分成消息头和消息体分别处理,具体实现请看下篇,本例中的源码可以点此处下载,多谢          

原文地址:https://www.cnblogs.com/upwifi/p/2155532.html