iOS開源加密相冊(cè)Agony的實(shí)現(xiàn)(二)

簡(jiǎn)介

雖然目前市面上有一些不錯(cuò)的加密相冊(cè)App,但不是內(nèi)置廣告,就是對(duì)上傳的張數(shù)有所限制。本文介紹了一個(gè)加密相冊(cè)的制作過程,該加密相冊(cè)將包括多密碼(輸入不同的密碼即可訪問不同的空間,可掩人耳目)、WiFi傳圖、照片文件加密等功能。目前項(xiàng)目和文章會(huì)同時(shí)前進(jìn),項(xiàng)目的源代碼可以在github上下載。
點(diǎn)擊前往GitHub

概述

上一篇文章主要介紹了賬戶存儲(chǔ)類與工具類的設(shè)計(jì),這一篇將通過工具類,實(shí)現(xiàn)登陸與注冊(cè)的交互界面。

登錄控制器與視圖設(shè)計(jì)

自定義控制器視圖

為了分離視圖邏輯與業(yè)務(wù)邏輯,控制器視圖用一個(gè)自定義類去管理,在控制器的loadView方法中將自定義視圖指定為控制器視圖。
文件結(jié)構(gòu)如下。


指定自定義視圖為控制器視圖的方法如下。
由于要使用自定義視圖SGWelcomeView的一些API,因此需要將其引用,否則直接通過view獲取的還需要類型強(qiáng)轉(zhuǎn)才能使用。

@interface SGWelcomeViewController ()

@property (nonatomic, weak) SGWelcomeView *welcomeView;

@end

@implementation SGWelcomeViewController

- (void)loadView {
    SGWelcomeView *view = [SGWelcomeView new];
    self.view = view;
    self.welcomeView = view;
}

登錄界面設(shè)計(jì)

登錄界面如下圖所示。


登錄界面

嘗試Touch ID的登錄方式

如果設(shè)備支持Touch ID,則會(huì)先嘗試Touch ID的驗(yàn)證方式,如果驗(yàn)證失敗則要求輸入密碼。
在登錄控制器出現(xiàn)時(shí),先清空已經(jīng)登錄的賬戶,并且嘗試Touch ID登錄的實(shí)現(xiàn)如下。

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    [SGAccountManager  sharedManager].currentAccount = nil;
    [self handleTouchIDLogin];
}
- (void)handleTouchIDLogin {
    LAContext *context = [LAContext new];
    if([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:nil]) {
        [context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:@"Agony need your Touch ID to login" reply:^(BOOL success, NSError * _Nullable error) {
            if (success) {
                SGAccount *account = [[SGAccountManager sharedManager] getTouchIDAccount];
                [self loginWithAccount:account];
            } else {
                [self handleCommonLogin];
            }
        }];
    } else {
        [self handleCommonLogin];
    }
}

Touch ID的驗(yàn)證通過LAContext實(shí)現(xiàn),成功則通過Touch ID綁定的密碼登錄,失敗則進(jìn)行密碼登錄(調(diào)用handleCommonLogin方法)。
需要注意Touch ID的回調(diào)是在子線程,如果涉及到UI操作,不要忘記放到主線程操作。

密碼登錄方式

密碼登錄通過調(diào)用handleCommonLogin方法實(shí)現(xiàn),該方法指定登錄view的block回調(diào),并且使得密碼輸入框成為第一響應(yīng)者。

- (void)handleCommonLogin {
    WS();  // 定義weakSelf的宏
    [self.welcomeView setWelcomeHandler:^(SGAccount *account) {
        [weakSelf loginWithAccount:account];
    }];
}

當(dāng)用戶輸入完密碼按下Return鍵,會(huì)回調(diào)該block來(lái)執(zhí)行登錄。注意到Touch ID和密碼登錄最后執(zhí)行的方法都是loginWithAccount:方法,該方法的實(shí)現(xiàn)如下。

- (void)loginWithAccount:(SGAccount *)account {
    dispatch_async(dispatch_get_main_queue(), ^{
        if (!account) {
            [MBProgressHUD showError:@"Password Error"];
            return;
        }
        [SGAccountManager sharedManager].currentAccount = account;
        AppDelegate *app = [UIApplication sharedApplication].delegate;
        app.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[SGHomeViewController new]];
    });
}

之所以使用GCD,是因?yàn)樵赥ouch ID的回調(diào)里也進(jìn)行了該方法的調(diào)用,而Touch ID的回調(diào)是子線程。
在登錄驗(yàn)證時(shí)如果密碼驗(yàn)證成功返回賬戶對(duì)象,失敗則返回空,因此通過賬戶是否為空可以判斷是否登錄完成。如果登錄成功則保存登陸成功的對(duì)象到賬戶管理單例中,并且切換根控制器為相冊(cè)主頁(yè)的控制器。

登錄視圖的細(xì)節(jié)

對(duì)于屏幕尺寸較小的手機(jī),鍵盤可能會(huì)遮擋輸入框,應(yīng)該監(jiān)聽鍵盤的顯示與隱藏事件,判斷鍵盤是否遮擋了輸入框,從而決定是否要向上移動(dòng)視圖。
登錄界面包含了圖標(biāo)、文本和輸入框,三者通過約束來(lái)定位在父視圖SGWelcomeView上,在位移時(shí),為了方便起見,將整個(gè)父視圖向上平移,平移通過transform來(lái)實(shí)現(xiàn),具體如下。

注冊(cè)與注銷通知

由于視圖通過代碼框架,因此一定會(huì)調(diào)用initWithFrame:方法,在該方法中注冊(cè)通知。

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardHide:) name:UIKeyboardWillHideNotification object:nil];

在dealloc方法中注銷通知。

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
處理鍵盤的顯示

由于監(jiān)聽的是鍵盤即將動(dòng)作的事件,因此鍵盤的最終位置應(yīng)通過endFrame來(lái)拿到。判斷鍵盤是否遮擋輸入框的關(guān)鍵是看鍵盤的topY是否小于輸入框的bottomY,如果topY小于bottomY,則應(yīng)該將整個(gè)視圖向上平移bottomY-topY,為了美觀,應(yīng)該多平移一段間距,deltaY就是應(yīng)該平移的距離,向上為負(fù)值。
條件判斷中除去delta還判斷了視圖是否還實(shí)施了變換,這是因?yàn)樽儞Q是針對(duì)整個(gè)父視圖的,而計(jì)算時(shí)獲取的輸入框坐標(biāo)是相對(duì)父視圖的,因此父視圖的變換不會(huì)影響到輸入框坐標(biāo),鍵盤顯示可能被多次調(diào)用,為了保證不會(huì)重復(fù)的將視圖向上平移,需要判斷是否已經(jīng)進(jìn)行過變換了。

- (void)keyboardShow:(NSNotification *)nof {
    CGRect endFrame = [nof.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    CGFloat endY = endFrame.origin.y;
    CGFloat deltaY = endY - CGRectGetMaxY(self.pwdFiled.frame) - 10;
    if (deltaY < 0 && CGAffineTransformEqualToTransform(self.transform, CGAffineTransformIdentity)) {
        self.transform = CGAffineTransformTranslate(self.transform, 0, deltaY);
    }
}
處理鍵盤的隱藏

鍵盤隱藏時(shí)只需要復(fù)原變換即可。

- (void)keyboardHide:(NSNotification *)nof {
    self.transform = CGAffineTransformIdentity;
}

如果想要讓鍵盤的出現(xiàn)、消失與視圖位移同步移動(dòng),可以通過通知對(duì)象拿到鍵盤移動(dòng)的duration,然后將變換寫在UIView的動(dòng)畫block中。

注冊(cè)控制器與視圖設(shè)計(jì)

注冊(cè)控制器的設(shè)計(jì)與登錄控制器設(shè)計(jì)一致,文件結(jié)構(gòu)如下。



界面如下。


注冊(cè)頁(yè)面

注冊(cè)頁(yè)面與登錄頁(yè)面一樣,也是通過block回調(diào)到控制器,來(lái)處理注冊(cè),因?yàn)槊總€(gè)密碼對(duì)應(yīng)一個(gè)存儲(chǔ)空間,注冊(cè)時(shí)要求密碼不能與已有賬戶重復(fù)。當(dāng)輸入完確認(rèn)密碼并按下鍵盤上的Return鍵后通過block回調(diào),傳回密碼與確認(rèn)密碼,控制器處理的實(shí)現(xiàn)如下。
- (void)handleRegisterWithPassword:(NSString *)password confirm:(NSString *)confirm {
    // 密碼與確認(rèn)密碼必須一致,并且不為空
    if (![password isEqualToString:confirm]) {
        [MBProgressHUD showError:@"Passwords Do Not Match"];
        return;
    } else if (!password.length) {
        [MBProgressHUD showError:@"Password Cannot be Empty"];
        return;
    }
    // 使用賬戶管理對(duì)象來(lái)處理注冊(cè)的業(yè)務(wù)邏輯
    SGAccountManager *mgr = [SGAccountManager sharedManager];
    NSString *errorMessage = nil;
    [mgr registerAccountWithPassword:password errorMessage:&errorMessage];
    if (errorMessage == nil) {
        // 注冊(cè)成功則回到登錄頁(yè)面
        [MBProgressHUD showSuccess:@"Register Succeeded"];
        [self.navigationController popViewControllerAnimated:YES];
    } else {
        [MBProgressHUD showError:errorMessage];
    }
}

總結(jié)

本文主要介紹了登錄與注冊(cè)界面的實(shí)現(xiàn)細(xì)節(jié),歡迎關(guān)注項(xiàng)目后續(xù),項(xiàng)目的下載地址在本文的開頭可以找到。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,460評(píng)論 6 538
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,067評(píng)論 3 423
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,467評(píng)論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,468評(píng)論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,184評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,582評(píng)論 1 325
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,616評(píng)論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,794評(píng)論 0 289
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,343評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,096評(píng)論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,291評(píng)論 1 371
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,863評(píng)論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,513評(píng)論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,941評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,190評(píng)論 1 291
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,026評(píng)論 3 396
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,253評(píng)論 2 375

推薦閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,157評(píng)論 4 61
  • 為期半月的軍訓(xùn)生活是在一場(chǎng)聲勢(shì)浩大,陳辭激昂的開學(xué)典禮暨軍訓(xùn)動(dòng)員大會(huì)后開始的。要求全體新生以班為單位,以學(xué)院為更大...
    繁花千樹閱讀 762評(píng)論 0 5
  • 我身邊經(jīng)常有一些交際高手。他們總是能言善辯,能說(shuō)會(huì)道,不管在任何場(chǎng)合,任何地方面對(duì)任何人都是游刃有余。真是到了花見...
    幸福D蘇眉閱讀 5,252評(píng)論 0 2
  • 出來(lái)好像三天了吧… 思念我相公,相公一個(gè)人在北京,我跑杭州來(lái)瀟灑啦…其實(shí)很想跟你在一起的每個(gè)時(shí)間段,但生活總會(huì)有分...
    呆萌的阿喵小姐閱讀 179評(píng)論 0 0