ESFramework Demo之iPhone版--登录(续)

转自:http://www.cnblogs.com/upwifi/archive/2011/08/27/2155532.html

上一回我们只是画了一个界面,虽然我们看到了用于输入昵称和密码的文本框,但我们还没有给这两个文本框做输入键盘的订制。本文接着上篇,把后续的功能完成,其内容包括根据登陆协议构造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.returnKeyTypeUIReturnKeyNext;

    ((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中的 @interfaceRootViewController : UITableViewController<UITextFieldDelegate>说明RootViewController要实现UITextFieldDelegate协议中的方法,本例中的方法是-(BOOL)textFieldShouldReturn:(UITextField*)field, 由此方法我们可以对不同的UITextField对象做不同的处理代码如下:

 

 

    -(BOOL)textFieldShouldReturn:(UITextField*)field

 

    {

 

      if (field.tag == 1) {

 

        //NSLog(@"昵称");

 

        [field resignFirstResponder];

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

 

      else{

 

         //NSLog(@"");

 

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

 

      }

 

    }

 

 

  2.按登录协议构造byet流

 

 

    messageData = [NSMutableData data];

 

    Login *loginBody = [[Login allocinit];

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

    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:1text];

 

    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(22)];

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

 

       int messageBodyLen;

       [data getBytes:&messageBodyLen range:NSMakeRange(84)];

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

       int logonResult;

       switch (messageType) {

         case 116:                

 

         [data getBytes:&logonResult range:NSMakeRange(404)];

         if (logonResult==0) {

           NSLog(@"录成功");

           RapidEngineDemoAppDelegate* appData = [[UIApplication sharedApplicationdelegate];

 

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

posted @ 2013-04-25 09:36  ADTL  阅读(144)  评论(0)    收藏  举报