开源中国iOS客户端学习——(十二)用户登陆

简介:

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

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


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

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

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

 
    NSString *homeDirectory = NSHomeDirectory();    NSLog(@"path:%@", homeDirectory);

打印结果:   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文件,将其打开

154949993.png

154950176.png


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


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

155043408.png

155043398.png


从头文件中声明部分

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
- ( void )viewDidLoad
{
     [super viewDidLoad];
     [Tool clearWebViewBackground:webView];
     [self.webView setDelegate:self];
                                                                                                                                                       
     self.navigationItem.title = @ "登录" ;
     //决定是否显示用户名以及密码
     NSString *name = [Config Instance].getUserName;
     NSString *pwd = [Config Instance].getPwd;
//    如果用户名和密码存在,且不为空,取出付给相应text
     if  (name && ![name isEqualToString:@ "" ]) {
         self.txt_Name.text = name;
     }
     if  (pwd && ![pwd isEqualToString:@ "" ]) {
         self.txt_Pwd.text = pwd;
     }
                                                                                                                                                       
     UIBarButtonItem *btnLogin = [[UIBarButtonItem alloc] initWithTitle:@ "登录"  style:UIBarButtonItemStyleBordered target:self action:@selector(click_Login:)];
     self.navigationItem.rightBarButtonItem = btnLogin;
     self.view.backgroundColor = [Tool getBackgroundColor];
     self.webView.backgroundColor = [Tool getBackgroundColor];
//    web控件上信息
     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>" ;
     [self.webView loadHTMLString:html baseURL:nil];
     self.webView.hidden = NO;
}
  在 [Tool clearWebViewBackground:webView];作用描述不好,直接看方法
+ ( void )clearWebViewBackground:(UIWebView *)webView
{
     UIWebView *web = webView;
     for  (id v in web.subviews) {
         if  ([v isKindOfClass:[UIScrollView  class ]]) {
             [v setBounces:NO];
         }
     }
}

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

155213368.png

155213624.png


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


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


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

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

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


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


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


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

1
2
3
4
5
6
7
8
9
10
-( void )startNotice
{
     if  (isRunning) {
         return ;
     }
     else  {
         timer = [NSTimer scheduledTimerWithTimeInterval:60 target:self selector:@selector(timerUpdate) userInfo:nil repeats:YES];
         isRunning = YES;
     }
}


1
2
3
4
5
6
7
8
9
10
11
12
-( void )timerUpdate
{
     NSString * url = [NSString stringWithFormat:@ "%@?uid=%d" ,api_user_notice,[Config Instance].getUID];
     [[AFOSCClient sharedClient]getPath:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
                                                                                                      
         [Tool getOSCNotice2:operation.responseString];
                                                                                                      
     } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                                                                                                      
     }];
                                                                                                  
}

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

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




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

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

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



开源中国iOS客户端源码下载地址: http://git.oschina.net/oschina/iphone-app




     本文转自新风作浪 51CTO博客,原文链接:http://blog.51cto.com/duxinfeng/1206850,如需转载请自行联系原作者




相关文章
|
6月前
|
Linux Android开发 iOS开发
基于.Net开发的ChatGPT客户端,兼容Windows、IOS、安卓、MacOS、Linux
基于.Net开发的ChatGPT客户端,兼容Windows、IOS、安卓、MacOS、Linux
91 0
|
6月前
|
安全 前端开发 Android开发
鸿蒙开发|鸿蒙系统的介绍(为什么要学习鸿蒙开发|鸿蒙系统的官方定义|鸿蒙和安卓、ios的对比)
鸿蒙开发学习是一项探索性的工作,旨在开发一个全场景分布式操作系统,覆盖所有设备,让消费者能够更方便、更直观地使用各种设备。
301 6
鸿蒙开发|鸿蒙系统的介绍(为什么要学习鸿蒙开发|鸿蒙系统的官方定义|鸿蒙和安卓、ios的对比)
|
8月前
|
iOS开发
iOS UIKit Dynamics Demo 学习地址列表
iOS UIKit Dynamics Demo 学习地址列表
23 0
|
9月前
|
API 开发工具 iOS开发
一点就通,社交源码IOS客户端开发集成SDK
所谓SDK,全称是SoftwaredevelopmentKit,翻译成软件开发工具包。SDK用助开发某种软件,今天给大家简单讲解下如何在社交源码IOS客户端上开发集成 SDK。
|
9月前
|
存储 网络安全 数据安全/隐私保护
iOS 逆向编程(八)远程拷贝 - 客户端(电脑)通过 ssh 拷贝文件到服务端(手机)
iOS 逆向编程(八)远程拷贝 - 客户端(电脑)通过 ssh 拷贝文件到服务端(手机)
99 0
|
9月前
|
存储 网络安全 数据安全/隐私保护
iOS 逆向编程(七)客户端(手机)免密认证登录
iOS 逆向编程(七)客户端(手机)免密认证登录
102 0
|
10月前
|
Android开发 iOS开发 Windows
无影产品动态|iOS & Android客户端6.0.0版本发布,提升触控灵敏度,操作体验更丝滑
无影ios & Android客户端6.0.0版本发布!移动端触控体验更舒适,用户操作更便捷,一起来看看!
689 0
无影产品动态|iOS & Android客户端6.0.0版本发布,提升触控灵敏度,操作体验更丝滑
|
Web App开发 弹性计算 Android开发
阿里云无影云桌面客户端下载Win/Mac/iOS/安卓/Web端均支持
阿里云无影客户端下载系统Win/Mac/iOS/安卓/Web端均支持
3742 0
阿里云无影云桌面客户端下载Win/Mac/iOS/安卓/Web端均支持
|
iOS开发
iOS开发 - 写一个刷新的控件(未封装,适合新手学习,查看原理)
iOS开发 - 写一个刷新的控件(未封装,适合新手学习,查看原理)
130 0
iOS开发 - 写一个刷新的控件(未封装,适合新手学习,查看原理)
|
物联网 Android开发 iOS开发
iOS开发 - 蓝牙学习的总结
iOS开发 - 蓝牙学习的总结
130 0