您的位置:首页 > 移动开发 > IOS开发

开源中国IOS客户端学习

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

[cpp] view
plaincopy

-(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];将键值信息同步道本地;

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

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

[cpp] view
plaincopy

[cpp] view
plaincopy

<span style="font-family:Comic Sans MS;font-size:18px;"> NSString *homeDirectory = NSHomeDirectory();

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

#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

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

[cpp] view
plaincopy

- (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;

}

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

[cpp] view
plaincopy

+ (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 时就不会;





[cpp] view
plaincopy

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

}

[cpp] view
plaincopy

[cpp] view
plaincopy

// 登陆失败,隐藏显示的动画

- (void)requestFailed:(ASIHTTPRequest *)request

{

if (request.hud) {

[request.hud hide:YES];

}

}

[cpp] view
plaincopy

- (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如下,

[html] view
plaincopy

<?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

[cpp] view
plaincopy

- (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刷新一下用户信息,是否有新的粉丝或几条评论;

[cpp] view
plaincopy

-(void)startNotice

{

if (isRunning) {

return;

}

else {

timer = [NSTimer scheduledTimerWithTimeInterval:60 target:self selector:@selector(timerUpdate) userInfo:nil repeats:YES];

isRunning = YES;

}

}

[cpp] view
plaincopy

-(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请求获取的返回的信息(已经登陆情开源中国社区网站的况下)

[html] view
plaincopy

<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提示视图

原创博客欢迎转载分享,请注明出处 http://blog.csdn.net/duxinfeng2010
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: