天天看點

開源中國iOS用戶端學習——(十二)使用者登陸

1

2

3

4

5

6

7

8

9

10

<code>-(</code><code>void</code><code>)saveUserNameAndPwd:(NSString *)userName andPwd:(NSString *)pwd</code>

<code>{</code>

<code>    </code><code>NSUserDefaults * settings = [NSUserDefaults standardUserDefaults];</code>

<code>    </code><code>[settings removeObjectForKey:@</code><code>"UserName"</code><code>];</code>

<code>    </code><code>[settings removeObjectForKey:@</code><code>"Password"</code><code>];</code>

<code>    </code><code>[settings setObject:userName forKey:@</code><code>"UserName"</code><code>];</code>

<code>    </code><code>pwd = [AESCrypt encrypt:pwd password:@</code><code>"pwd"</code><code>];</code>

<code>    </code><code>[settings setObject:pwd forKey:@</code><code>"Password"</code><code>];</code>

<code>    </code><code>[settings synchronize];</code>

<code>}</code>

上面的方法使用了NSUserDefaults類,它也是以字典形式實作對資料功能,并将這些資料儲存到本地應用程式沙盒之中,這種方法适合儲存較小的資料,例如使用者登陸配置資訊;這段代碼首先是定義了一個對象,進行初始化,移除鍵值為UseName和Password的對象,防止資料混亂造成幹擾;然後就是重新設定鍵值資訊; [settings synchronize];将鍵值資訊同步道本地;

現在我們道沙盒中來看看這個使用者配置資訊

首先檢視應用程式沙盒的路徑 ,使用

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

從中不難看出儲存在本地沙盒中使用者的一些基本資訊,以及一些配置資訊,還記錄一些上次擷取資料時間等等;

登陸類在Setting目錄下的loginView類,先看看loginView.xib吧,界面比較簡陋,可能是缺美工吧;

從頭檔案中聲明部分

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

<code>#import &lt;UIKit/UIKit.h&gt;</code>

<code>#import "Tool.h"</code>

<code>#import "ProfileBase.h"</code>

<code>#import "MessageView.h"</code>

<code>#import "Config.h"</code>

<code>#import "MBProgressHUD.h"</code>

<code>#import "MyThread.h"</code>

<code>@interface LoginView : UIViewController&lt;UIWebViewDelegate&gt;</code>

<code>//    ASI類庫,擷取網絡請求,進行登陸驗證</code>

<code>    </code><code>ASIFormDataRequest *request;</code>

<code>//接受使用者名輸入</code>

<code>@property (strong, nonatomic) IBOutlet UITextField *txt_Name;</code>

<code>//接受使用者屬于密碼</code>

<code>@property (strong, nonatomic) IBOutlet UITextField *txt_Pwd;</code>

<code>//開關按鈕,設定使用者是否要記住使用者名和密碼</code>

<code>@property (strong, nonatomic) IBOutlet UISwitch *switch_Remember;</code>

<code>//标記作用,用于記錄請求資料傳回異常或錯誤時是否彈出一個警告</code>

<code>@property </code><code>BOOL</code> <code>isPopupByNotice;</code>

<code>//webView,布局一個手機上的web網頁,顯示說明資訊,在這個web頁面有富文本使用,直接可以跳轉到url上</code>

<code>@property (strong, nonatomic) IBOutlet UIWebView *webView;</code>

<code>//登陸處理</code>

<code>- (IBAction)click_Login:(id)sender;</code>

<code>//取消兩個textFile的第一響應對象</code>

<code>- (IBAction)textEnd:(id)sender;</code>

<code>//取消鍵盤第一響應對象,點選頁面推出鍵盤</code>

<code>- (IBAction)backgrondTouch:(id)sender;</code>

<code>//根據傳回的資料儲存使用者名和使用者ID到本地</code>

<code>- (</code><code>void</code><code>)analyseUserInfo:(NSString *)xml;</code>

<code>@end</code>

在實作檔案裡,粘貼上主要方法代碼

32

33

34

35

36

37

<code>- (</code><code>void</code><code>)viewDidLoad</code>

<code>    </code><code>[super viewDidLoad];</code>

<code>    </code><code>[Tool clearWebViewBackground:webView];</code>

<code>    </code><code>[self.webView setDelegate:self];</code>

<code>                                                                                                                                                      </code> 

<code>    </code><code>self.navigationItem.title = @</code><code>"登入"</code><code>;</code>

<code>    </code><code>//決定是否顯示使用者名以及密碼</code>

<code>    </code><code>NSString *name = [Config Instance].getUserName;</code>

<code>    </code><code>NSString *pwd = [Config Instance].getPwd;</code>

<code>//    如果使用者名和密碼存在,且不為空,取出付給相應text</code>

<code>    </code><code>if</code> <code>(name &amp;&amp; ![name isEqualToString:@</code><code>""</code><code>]) {</code>

<code>        </code><code>self.txt_Name.text = name;</code>

<code>    </code><code>}</code>

<code>    </code><code>if</code> <code>(pwd &amp;&amp; ![pwd isEqualToString:@</code><code>""</code><code>]) {</code>

<code>        </code><code>self.txt_Pwd.text = pwd;</code>

<code>    </code><code>UIBarButtonItem *btnLogin = [[UIBarButtonItem alloc] initWithTitle:@</code><code>"登入"</code> <code>style:UIBarButtonItemStyleBordered target:self action:@selector(click_Login:)];</code>

<code>    </code><code>self.navigationItem.rightBarButtonItem = btnLogin;</code>

<code>    </code><code>self.view.backgroundColor = [Tool getBackgroundColor];</code>

<code>    </code><code>self.webView.backgroundColor = [Tool getBackgroundColor];</code>

<code>//    web控件上資訊</code>

<code>    </code><code>NSString *html = @</code><code>"&lt;body style='background-color:#EBEBF3'&gt;1, 您可以在 &lt;a href='http://www.oschina.net'&gt;http://www.oschina.net&lt;/a&gt; 上免費注冊一個賬号用來登陸&lt;p /&gt;2, 如果您的賬号是使用OpenID的方式注冊的,那麼建議您在網頁上為賬号設定密碼&lt;p /&gt;3, 您可以點選 &lt;a href='http://www.oschina.net/question/12_52232'&gt;這裡&lt;/a&gt; 了解更多關于手機用戶端登入的問題&lt;/body&gt;"</code><code>;</code>

<code>    </code><code>[self.webView loadHTMLString:html baseURL:nil];</code>

<code>    </code><code>self.webView.hidden = NO;</code>

<code> </code><code>在 [Tool clearWebViewBackground:webView];作用描述不好,直接看方法</code>

<code>+ (</code><code>void</code><code>)clearWebViewBackground:(UIWebView *)webView</code>

<code>    </code><code>UIWebView *web = webView;</code>

<code>    </code><code>for</code> <code>(id v in web.subviews) {</code>

<code>        </code><code>if</code> <code>([v isKindOfClass:[UIScrollView </code><code>class</code><code>]]) {</code>

<code>            </code><code>[v setBounces:NO];</code>

<code>        </code><code>}</code>

[v setBounces:NO];  如果[v setBounces:YES]; 滾動上下滾動是出現空隙,不美觀,為NO  時就不會;

<code>- (IBAction)click_Login:(id)sender</code>

<code>//    擷取使用者名和密碼</code>

<code>    </code><code>NSString *name = self.txt_Name.text;</code>

<code>    </code><code>NSString *pwd = self.txt_Pwd.text;</code>

<code>//    使用ASI類庫請求登陸API,</code>

<code>    </code><code>request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:api_login_validate]];</code>

<code>    </code><code>[request setUseCookiePersistence:YES];</code>

<code>    </code><code>[request setPostValue:name forKey:@</code><code>"username"</code><code>];</code>

<code>    </code><code>[request setPostValue:pwd forKey:@</code><code>"pwd"</code><code>];</code>

<code>    </code><code>[request setPostValue:@</code><code>"1"</code> <code>forKey:@</code><code>"keep_login"</code><code>];</code>

<code>    </code><code>[request setDelegate:self];</code>

<code>//    失敗調用 requestFailed:</code>

<code>    </code><code>[request setDidFailSelector:@selector(requestFailed:)];</code>

<code>//    成功調用 equestLogin:</code>

<code>    </code><code>[request setDidFinishSelector:@selector(requestLogin:)];</code>

<code>//    開始請求</code>

<code>    </code><code>[request startAsynchronous];</code>

<code>//    動畫提示使用者等待</code>

<code>    </code><code>request.hud = [[MBProgressHUD alloc] initWithView:self.view];</code>

<code>    </code><code>[Tool showHUD:@</code><code>"正在登入"</code> <code>andView:self.view andHUD:request.hud];</code>

<code>//  登陸失敗,隐藏顯示的動畫</code>

<code>- (</code><code>void</code><code>)requestFailed:(ASIHTTPRequest *)request</code>

<code>    </code><code>if</code> <code>(request.hud) {</code>

<code>        </code><code>[request.hud hide:YES];</code>

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

<code>- (</code><code>void</code><code>)requestLogin:(ASIHTTPRequest *)request</code>

<code>//    根據請求回來的xml進行解析資料,判斷是否登陸成功</code>

<code>    </code><code>[Tool getOSCNotice:request];</code>

<code>//    将請求回來的資訊儲存在用戶端</code>

<code>    </code><code>ApiError *error = [Tool getApiError:request];</code>

<code>                                                                                                                              </code> 

<code>    </code><code>if</code> <code>(error == nil) {</code>

<code>        </code><code>[Tool ToastNotification:request.responseString andView:self.view andLoading:NO andIsBottom:NO];</code>

<code>    </code><code>switch</code> <code>(error.errorCode) {</code>

<code>                                                                                                                                   </code> 

<code>        </code><code>case</code> <code>1:</code>

<code>        </code><code>{</code>

<code>            </code><code>[[Config Instance] saveCookie:YES];</code>

<code>            </code><code>if</code> <code>(isPopupByNotice == NO)</code>

<code>            </code><code>{</code>

<code>                </code><code>NSUserDefaults  *d= [NSUserDefaults standardUserDefaults];</code>

<code>                </code><code>[self.navigationController popViewControllerAnimated:YES];</code>

<code>            </code><code>}</code>

<code>                                                                                                                                       </code> 

<code>            </code><code>//處理是否記住使用者名或者密碼</code>

<code>            </code><code>if</code> <code>(self.switch_Remember.isOn)</code>

<code>                </code><code>[[Config Instance] saveUserNameAndPwd:self.txt_Name.text andPwd:self.txt_Pwd.text];</code>

<code>            </code><code>//否則需要清空使用者名于密碼</code>

<code>            </code><code>else</code>

<code>                </code><code>[[Config Instance] saveUserNameAndPwd:@</code><code>""</code> <code>andPwd:@</code><code>""</code><code>];</code>

<code>            </code><code>//傳回的處理</code>

<code>            </code><code>if</code> <code>([Config Instance].viewBeforeLogin)</code>

<code>                </code><code>if</code><code>([[Config Instance].viewNameBeforeLogin isEqualToString:@</code><code>"ProfileBase"</code><code>])</code>

<code>                </code><code>{</code>

<code>                    </code><code>ProfileBase *_parent = (ProfileBase *)[Config Instance].viewBeforeLogin;</code>

<code>                    </code><code>_parent.isLoginJustNow = YES;</code>

<code>                </code><code>}</code>

<code>            </code><code>//開始分析 uid 等等資訊</code>

<code>            </code><code>[self analyseUserInfo:request.responseString];</code>

<code>            </code><code>//分析是否需要退回</code>

<code>            </code><code>if</code> <code>(self.isPopupByNotice) {</code>

<code>//            檢視startNotice方法可知是一個定時器,每隔60s重新整理一下使用者資訊,是否有新的粉絲或幾條評論</code>

<code>            </code><code>[[MyThread Instance] startNotice];</code>

<code>            </code><code>break</code><code>;</code>

<code>        </code><code>case</code> <code>0:</code>

<code>        </code><code>case</code> <code>-1:</code>

<code>//            傳回 當error.errorCode =0 || 1的時候,顯示相關錯誤資訊</code>

<code>            </code><code>[Tool ToastNotification:[NSString stringWithFormat:@</code><code>"錯誤 %@"</code><code>,error.errorMessage] andView:self.view andLoading:NO andIsBottom:NO];</code>

ApiError 這個類看起來可能很迷惑人,它并不完全像字面意思那樣指的是錯誤的api資訊,而是根據請求傳回來的數字進行判斷。如果error.errorCode = 1表示成功傳回了使用者的資料,0,-1就可能由于伺服器網絡等原因不能正确傳回資料;

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

<code>&lt;?</code><code>xml</code> <code>version</code><code>=</code><code>"1.0"</code> <code>encoding</code><code>=</code><code>"UTF-8"</code><code>?&gt;</code>

<code>&lt;</code><code>oschina</code><code>&gt;</code>

<code>  </code><code>&lt;</code><code>result</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>errorCode</code><code>&gt;1&lt;/</code><code>errorCode</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>errorMessage</code><code>&gt;</code><code>&lt;![CDATA[登入成功]]&gt;</code><code>&lt;/</code><code>errorMessage</code><code>&gt;</code>

<code>  </code><code>&lt;/</code><code>result</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>user</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>uid</code><code>&gt;112617&lt;/</code><code>uid</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>location</code><code>&gt;</code><code>&lt;![CDATA[河南 南陽]]&gt;</code><code>&lt;/</code><code>location</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>name</code><code>&gt;</code><code>&lt;![CDATA[新風作浪]]&gt;</code><code>&lt;/</code><code>name</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>followers</code><code>&gt;1&lt;/</code><code>followers</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>fans</code><code>&gt;0&lt;/</code><code>fans</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>score</code><code>&gt;1&lt;/</code><code>score</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>portrait</code><code>&gt;http://static.oschina.net/uploads/user/56/112617_100.jpg?t=1350377690000&lt;/</code><code>portrait</code><code>&gt;</code>

<code>  </code><code>&lt;/</code><code>user</code><code>&gt;</code>

<code>  </code><code>&lt;</code><code>notice</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>atmeCount</code><code>&gt;0&lt;/</code><code>atmeCount</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>msgCount</code><code>&gt;0&lt;/</code><code>msgCount</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>reviewCount</code><code>&gt;0&lt;/</code><code>reviewCount</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>newFansCount</code><code>&gt;0&lt;/</code><code>newFansCount</code><code>&gt;</code>

<code>&lt;/</code><code>notice</code><code>&gt;</code>

<code>&lt;/</code><code>oschina</code><code>&gt;</code>

<code>&lt;!-- Generated by OsChina.NET (init:3[ms],page:3[ms],ip:61.163.231.198) --&gt;</code>

在 [self analyseUserInfo:request.responseString]方法中, 根據請求成功傳回的xml,解析使用者名和UID,儲存使用者的UID

<code>- (</code><code>void</code><code>)analyseUserInfo:(NSString *)xml</code>

<code>    </code><code>@</code><code>try</code> <code>{</code>

<code>        </code><code>TBXML *_xml = [[TBXML alloc] initWithXMLString:xml error:nil];</code>

<code>        </code><code>TBXMLElement *root = _xml.rootXMLElement;</code>

<code>        </code><code>TBXMLElement *user = [TBXML childElementNamed:@</code><code>"user"</code> <code>parentElement:root];</code>

<code>        </code><code>TBXMLElement *uid = [TBXML childElementNamed:@</code><code>"uid"</code> <code>parentElement:user];</code>

<code>        </code><code>//擷取uid</code>

<code>        </code><code>[[Config Instance] saveUID:[[TBXML textForElement:uid] intValue]];</code>

<code>    </code><code>@</code><code>catch</code> <code>(NSException *exception) {</code>

<code>        </code><code>[NdUncaughtExceptionHandler TakeException:exception];</code>

<code>    </code><code>@finally {</code>

<code>                                                                                                              </code> 

<code>                                                                                                          </code> 

在後面也看到[[MyThread Instance] startNotice];看看startNotice方法,是一個定時器,每隔60s重新整理一下使用者資訊,是否有新的粉絲或幾條評論;

<code>-(</code><code>void</code><code>)startNotice</code>

<code>    </code><code>if</code> <code>(isRunning) {</code>

<code>        </code><code>return</code><code>;</code>

<code>    </code><code>else</code> <code>{</code>

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

<code>        </code><code>isRunning = YES;</code>

<code>-(</code><code>void</code><code>)timerUpdate</code>

<code>    </code><code>NSString * url = [NSString stringWithFormat:@</code><code>"%@?uid=%d"</code><code>,api_user_notice,[Config Instance].getUID];</code>

<code>    </code><code>[[AFOSCClient sharedClient]getPath:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {</code>

<code>                                                                                                     </code> 

<code>        </code><code>[Tool getOSCNotice2:operation.responseString];</code>

<code>    </code><code>} failure:^(AFHTTPRequestOperation *operation, NSError *error) {</code>

<code>    </code><code>}];</code>

<code>                                                                                                 </code> 

   url請求擷取傳回的資訊(已經登陸情開源中國社群網站的況下)

<code>&lt;</code><code>notice</code><code>&gt;</code>

<code>&lt;</code><code>atmeCount</code><code>&gt;0&lt;/</code><code>atmeCount</code><code>&gt;</code>

<code>&lt;</code><code>msgCount</code><code>&gt;0&lt;/</code><code>msgCount</code><code>&gt;</code>

<code>&lt;</code><code>reviewCount</code><code>&gt;0&lt;/</code><code>reviewCount</code><code>&gt;</code>

<code>&lt;</code><code>newFansCount</code><code>&gt;0&lt;/</code><code>newFansCount</code><code>&gt;</code>

<code>&lt;!--</code>

<code> </code><code>Generated by OsChina.NET (init:1[ms],page:1[ms],ip:61.163.231.198)</code>

<code>--&gt;</code>

關于本文提到的幾個動畫過渡顯示效果請看

     本文轉自新風作浪 51CTO部落格,原文連結:http://blog.51cto.com/duxinfeng/1206850,如需轉載請自行聯系原作者