登陆功能

上一篇博客  开源中国iOS客户端学习——(十一)AES加密 中提到将用户名和密码保存到了本地沙盒之中,在从本地读取用户名和密码,这是一个怎样的过程?

[cpp] view plaincopy
 
  1. -(void)saveUserNameAndPwd:(NSString *)userName andPwd:(NSString *)pwd  
  2. {  
  3.     NSUserDefaults * settings = [NSUserDefaults standardUserDefaults];  
  4.     [settings removeObjectForKey:@"UserName"];  
  5.     [settings removeObjectForKey:@"Password"];  
  6.     [settings setObject:userName forKey:@"UserName"];  
  7.       
  8.     pwd = [AESCrypt encrypt:pwd password:@"pwd"];  
  9.       
  10.     [settings setObject:pwd forKey:@"Password"];  
  11.     [settings synchronize];  
  12. }  


上面的方法使用了NSUserDefaults类,它也是以字典形式实现对数据功能,并将这些数据保存到本地应用程序沙盒之中,这种方法适合保存较小的数据,例如用户登陆配置信息;这段代码首先是定义了一个对象,进行初始化,移除键值为UseName和Password的对象,防止数据混乱造成干扰;然后就是重新设置键值信息; [settings synchronize];将键值信息同步道本地;

现在我们道沙盒中来看看这个用户配置信息

首先查看应用程序沙盒的路径 ,使用

[cpp] view plaincopy
 
  1.   
[cpp] view plaincopy
 
  1. <span style="font-family:Comic Sans MS;font-size:18px;">    NSString *homeDirectory = NSHomeDirectory();  
  2.     NSLog(@"path:%@", homeDirectory);</span>  

打印结果:   path:/Users/DolBy/Library/Application Support/iPhone Simulator/5.1/Applications/55C49712-AD95-49E0-B3B9-694DC7D26E94

但是在我的DolBy用户下并没有Library这个目录,这是因为系统隐藏了这些文件目录,现在需要显示这些隐藏的文件,打开终端输入 defaults write com.apple.finder AppleShowAllFiles -bool true  回车,然后重启Finder(不会?请看 查看iOS沙盒(SanBox)文件),找到55C49712-AD95-49E0-B3B9-694DC7D26E94目录下的Library/Preferences下的 net.oschina.iosapp.plist文件,将其打开


 


 

从中不难看出保存在本地沙盒中用户的一些基本信息,以及一些配置信息,还记录一些上次获取数据时间等等;

 

登陆类在Setting目录下的loginView类,先看看loginView.xib吧,界面比较简陋,可能是缺美工吧;


从头文件中声明部分

[cpp] view plaincopy
 
  1. #import <UIKit/UIKit.h>  
  2. #import "Tool.h"  
  3. #import "ProfileBase.h"  
  4. #import "MessageView.h"  
  5. #import "Config.h"  
  6. #import "MBProgressHUD.h"  
  7. #import "MyThread.h"  
  8.   
  9. @interface LoginView : UIViewController<UIWebViewDelegate>   
  10. {  
  11. //    ASI类库,获取网络请求,进行登陆验证  
  12.     ASIFormDataRequest *request;  
  13. }  
  14. //接受用户名输入  
  15. @property (strong, nonatomic) IBOutlet UITextField *txt_Name;  
  16. //接受用户属于密码  
  17. @property (strong, nonatomic) IBOutlet UITextField *txt_Pwd;  
  18. //开关按钮,设置用户是否要记住用户名和密码  
  19. @property (strong, nonatomic) IBOutlet UISwitch *switch_Remember;  
  20. //标记作用,用于记录请求数据返回异常或错误时是否弹出一个警告  
  21. @property BOOL isPopupByNotice;  
  22. //webView,布局一个手机上的web网页,显示说明信息,在这个web页面有富文本使用,直接可以跳转到url上  
  23. @property (strong, nonatomic) IBOutlet UIWebView *webView;  
  24.   
  25. //登陆处理  
  26. - (IBAction)click_Login:(id)sender;  
  27. //取消两个textFile的第一响应对象  
  28. - (IBAction)textEnd:(id)sender;  
  29. //取消键盘第一响应对象,点击页面推出键盘  
  30. - (IBAction)backgrondTouch:(id)sender;  
  31. //根据返回的数据保存用户名和用户ID到本地  
  32. - (void)analyseUserInfo:(NSString *)xml;  
  33.   
  34. @end  


在实现文件里,粘贴上主要方法代码

[cpp] view plaincopy
 
  1. - (void)viewDidLoad  
  2. {  
  3.     [super viewDidLoad];  
  4.   
  5.     [Tool clearWebViewBackground:webView];  
  6.     [self.webView setDelegate:self];  
  7.       
  8.     self.navigationItem.title = @"登录";  
  9.     //决定是否显示用户名以及密码  
  10.     NSString *name = [Config Instance].getUserName;  
  11.     NSString *pwd = [Config Instance].getPwd;  
  12. //    如果用户名和密码存在,且不为空,取出付给相应text  
  13.     if (name && ![name isEqualToString:@""]) {  
  14.         self.txt_Name.text = name;  
  15.     }  
  16.     if (pwd && ![pwd isEqualToString:@""]) {  
  17.         self.txt_Pwd.text = pwd;  
  18.     }  
  19.       
  20.     UIBarButtonItem *btnLogin = [[UIBarButtonItem alloc] initWithTitle:@"登录" style:UIBarButtonItemStyleBordered target:self action:@selector(click_Login:)];  
  21.     self.navigationItem.rightBarButtonItem = btnLogin;  
  22.     self.view.backgroundColor = [Tool getBackgroundColor];  
  23.     self.webView.backgroundColor = [Tool getBackgroundColor];  
  24. //    web控件上信息  
  25.     NSString *html = @"<body style='background-color:#EBEBF3'>1, 您可以在 <a href='http://www.oschina.net'>http://www.oschina.net</a> 上免费注册一个账号用来登陆<p />2, 如果您的账号是使用OpenID的方式注册的,那么建议您在网页上为账号设置密码<p />3, 您可以点击 <a href='http://www.oschina.net/question/12_52232'>这里</a> 了解更多关于手机客户端登录的问题</body>";  
  26.     [self.webView loadHTMLString:html baseURL:nil];  
  27.     self.webView.hidden = NO;  
  28. }   

 在 [ToolclearWebViewBackground:webView];作用描述不好,直接看方法

 

[cpp] view plaincopy
 
  1. + (void)clearWebViewBackground:(UIWebView *)webView  
  2. {  
  3.     UIWebView *web = webView;  
  4.     for (id v in web.subviews) {  
  5.         if ([v isKindOfClass:[UIScrollView class]]) {  
  6.             [v setBounces:NO];  
  7.         }  
  8.     }  
  9. }  

[v setBounces:NO];  如果[v setBounces:YES]; 滚动上下滚动是出现空隙,不美观,为NO  时就不会;

  

 

[cpp] view plaincopy
 
  1. - (IBAction)click_Login:(id)sender   
  2. {  
  3. //    获取用户名和密码  
  4.     NSString *name = self.txt_Name.text;  
  5.     NSString *pwd = self.txt_Pwd.text;  
  6. //    使用ASI类库请求登陆API,  
  7.     request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:api_login_validate]];  
  8.     [request setUseCookiePersistence:YES];  
  9.     [request setPostValue:name forKey:@"username"];  
  10.     [request setPostValue:pwd forKey:@"pwd"];  
  11.     [request setPostValue:@"1" forKey:@"keep_login"];  
  12.     [request setDelegate:self];  
  13. //    失败调用 requestFailed:  
  14.     [request setDidFailSelector:@selector(requestFailed:)];  
  15. //    成功调用 equestLogin:  
  16.     [request setDidFinishSelector:@selector(requestLogin:)];  
  17. //    开始请求  
  18.     [request startAsynchronous];  
  19. //    动画提示用户等待  
  20.     request.hud = [[MBProgressHUD alloc] initWithView:self.view];  
  21.     [Tool showHUD:@"正在登录" andView:self.view andHUD:request.hud];  
  22. }  
[cpp] view plaincopy
 
  1.   
[cpp] view plaincopy
 
  1. //  登陆失败,隐藏显示的动画  
  2. - (void)requestFailed:(ASIHTTPRequest *)request  
  3. {  
  4.     if (request.hud) {  
  5.         [request.hud hide:YES];  
  6.     }  
  7. }  

 

[cpp] view plaincopy
 
  1. - (void)requestLogin:(ASIHTTPRequest *)request  
  2. {  
  3.     if (request.hud) {  
  4.         [request.hud hide:YES];  
  5.     }  
  6. //    根据请求回来的xml进行解析数据,判断是否登陆成功  
  7.     [Tool getOSCNotice:request];  
  8. //    将请求回来的信息保存在客户端  
  9.     [request setUseCookiePersistence:YES];  
  10.     ApiError *error = [Tool getApiError:request];  
  11.      
  12.     if (error == nil) {  
  13.         [Tool ToastNotification:request.responseString andView:self.view andLoading:NO andIsBottom:NO];  
  14.     }  
  15.     switch (error.errorCode) {  
  16.           
  17.         case 1:  
  18.         {  
  19.             [[Config Instance] saveCookie:YES];  
  20.             if (isPopupByNotice == NO)   
  21.             {  
  22.                 NSUserDefaults  *d= [NSUserDefaults standardUserDefaults];  
  23.                 [self.navigationController popViewControllerAnimated:YES];  
  24.             }  
  25.               
  26.             //处理是否记住用户名或者密码  
  27.             if (self.switch_Remember.isOn)   
  28.             {  
  29.                 [[Config Instance] saveUserNameAndPwd:self.txt_Name.text andPwd:self.txt_Pwd.text];  
  30.             }  
  31.             //否则需要清空用户名于密码  
  32.             else  
  33.             {  
  34.                 [[Config Instance] saveUserNameAndPwd:@"" andPwd:@""];  
  35.             }  
  36.             //返回的处理  
  37.   
  38.             if ([Config Instance].viewBeforeLogin)   
  39.             {  
  40.                 if([[Config Instance].viewNameBeforeLogin isEqualToString:@"ProfileBase"])  
  41.                 {  
  42.                     ProfileBase *_parent = (ProfileBase *)[Config Instance].viewBeforeLogin;  
  43.                     _parent.isLoginJustNow = YES;  
  44.                 }  
  45.             }  
  46.               
  47.             //开始分析 uid 等等信息  
  48.             [self analyseUserInfo:request.responseString];  
  49.             //分析是否需要退回  
  50.             if (self.isPopupByNotice) {  
  51.                 [self.navigationController popViewControllerAnimated:YES];  
  52.             }  
  53. //            查看startNotice方法可知是一个定时器,每隔60s刷新一下用户信息,是否有新的粉丝或几条评论  
  54.             [[MyThread Instance] startNotice];  
  55.         }  
  56.             break;  
  57.         case 0:  
  58.         case -1:  
  59.         {  
  60. //            返回 当error.errorCode =0 || 1的时候,显示相关错误信息  
  61.             [Tool ToastNotification:[NSString stringWithFormat:@"错误 %@",error.errorMessage] andView:self.view andLoading:NO andIsBottom:NO];  
  62.         }  
  63.             break;  
  64.     }  
  65. }  



ApiError 这个类看起来可能很迷惑人,它并不完全像字面意思那样指的是错误的api信息,而是根据请求返回来的数字进行判断。如果error.errorCode = 1表示成功返回了用户的数据,0,-1就可能由于服务器网络等原因不能正确返回数据;

在ApiError *error = [Tool getApiError:request];中,打印 request.responseString如下,

 

[html] view plaincopy
 
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2.   
  3.   
  4. <oschina>  
  5.   <result>  
  6.     <errorCode>1</errorCode>  
  7.     <errorMessage><![CDATA[登录成功]]></errorMessage>  
  8.   </result>  
  9.     <user>  
  10.     <uid>112617</uid>  
  11.     <location><![CDATA[河南 南阳]]></location>  
  12.     <name><![CDATA[新风作浪]]></name>  
  13.     <followers>1</followers>  
  14.     <fans>0</fans>  
  15.     <score>1</score>  
  16.     <portrait>http://static.oschina.net/uploads/user/56/112617_100.jpg?t=1350377690000</portrait>  
  17.   </user>  
  18.   <notice>  
  19.     <atmeCount>0</atmeCount>  
  20.     <msgCount>0</msgCount>  
  21.     <reviewCount>0</reviewCount>  
  22.     <newFansCount>0</newFansCount>  
  23. </notice>  
  24. </oschina>  
  25. <!-- Generated by OsChina.NET (init:3[ms],page:3[ms],ip:61.163.231.198) -->  



在 [self analyseUserInfo:request.responseString]方法中, 根据请求成功返回的xml,解析用户名和UID,保存用户的UID

[cpp] view plaincopy
 
  1. - (void)analyseUserInfo:(NSString *)xml  
  2. {  
  3.     @try {  
  4.         TBXML *_xml = [[TBXML alloc] initWithXMLString:xml error:nil];  
  5.         TBXMLElement *root = _xml.rootXMLElement;      
  6.         TBXMLElement *user = [TBXML childElementNamed:@"user" parentElement:root];  
  7.         TBXMLElement *uid = [TBXML childElementNamed:@"uid" parentElement:user];  
  8.         //获取uid  
  9.         [[Config Instance] saveUID:[[TBXML textForElement:uid] intValue]];  
  10.     }  
  11.     @catch (NSException *exception) {  
  12.         [NdUncaughtExceptionHandler TakeException:exception];  
  13.     }  
  14.     @finally {  
  15.           
  16.     }  
  17.       
  18. }  
 

在后面也看到[[MyThread Instance] startNotice];看看startNotice方法,是一个定时器,每隔60s刷新一下用户信息,是否有新的粉丝或几条评论;

 

[cpp] view plaincopy
 
  1. -(void)startNotice  
  2. {  
  3.     if (isRunning) {  
  4.         return;  
  5.     }  
  6.     else {  
  7.         timer = [NSTimer scheduledTimerWithTimeInterval:60 target:self selector:@selector(timerUpdate) userInfo:nil repeats:YES];  
  8.         isRunning = YES;  
  9.     }  
  10. }  
[cpp] view plaincopy
 
  1. -(void)timerUpdate  
  2. {  
  3.     NSString * url = [NSString stringWithFormat:@"%@?uid=%d",api_user_notice,[Config Instance].getUID];  
  4.     [[AFOSCClient sharedClient]getPath:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {  
  5.           
  6.         [Tool getOSCNotice2:operation.responseString];  
  7.           
  8.     } failure:^(AFHTTPRequestOperation *operation, NSError *error) {  
  9.           
  10.     }];  
  11.       
  12. }  

 

url请求获取的返回的信息(已经登陆情开源中国社区网站的况下)

[html] view plaincopy
 
  1. <oschina>  
  2. <notice>  
  3. <atmeCount>0</atmeCount>  
  4. <msgCount>0</msgCount>  
  5. <reviewCount>0</reviewCount>  
  6. <newFansCount>0</newFansCount>  
  7. </notice>  
  8. </oschina>  
  9. <!-- 
  10.  Generated by OsChina.NET (init:1[ms],page:1[ms],ip:61.163.231.198)  
  11. -->  

 

关于本文提到的几个动画过渡显示效果请看

[Tool showHUD:@"正在登录" andView:self.view andHUD:request.hud];    MBProgressHUD特效

[Tool ToastNotification:[NSString stringWithFormat:@"错误 %@",error.errorMessage] andView:self.view andLoading:NO andIsBottom:NO];       GCDiscreetNotificationView提示视图

 

原文地址:https://www.cnblogs.com/yulang314/p/3587039.html