Sagit.Framework For IOS 開發框架入門教程3:Start引導頁及框架佈局和隱藏事件的內幕

来源:http://www.cnblogs.com/cyq1162/archive/2017/12/20/8070502.html
-Advertisement-
Play Games

框架依舊在快速更新著:在重構、簡化代碼,統一標準的過程中。中間也遇到各種坑,不過好在一步一腳印的解決了。雖然還有些功能還在思考,不過教程,還是得補上:這篇就寫寫StartController,實現的代碼雖少,但原理很精彩!!! ...


前言:

框架依舊在快速更新著:在重構、簡化代碼,統一標準的過程中。

中間也遇到各種坑,不過好在一步一腳印的解決了。

雖然還有些功能還在思考,不過教程,還是得補上:

上篇文章:Sagit.Framework For IOS 開發框架入門開發教程2:一行代碼實現引導頁

裡面講到,引導完後,根據是否存在的Token來解決跳轉到StartController還是MainController。

這篇就寫寫StartController,實現的代碼雖少,但原理很精彩!!!

Sagit 實現登陸註冊引導頁

從WelcomleController中,現在跳到了StartController了:

呈現的內容如下圖:(為不影響整體,這圖寬高設的的很小,大伙可以新開視窗看大圖):

這個界面,除了基礎的佈局,還有兩個事件:

1:點立即註冊:跳轉到註冊頁。

2:點登錄:或跳轉到登錄頁。

整體的效果如下:

這裡把View和Controller分開文件處理:

看看StartView的佈局的全部代碼:(下麵是我本人簡化後的代碼,以前的代碼多到嚇死人)

#import "STView.h"

@interface StartView : STView  //StartView.h

@end


@implementation StartView    //StartView.m

- (void)initUI
{
  
if(self.STController!=nil && self.STController.navigationController==nil){

      [self.STController asRoot:RootViewNavigationType];} 

    [self needNavigationBar:NO setNavBar:YES];//隱藏導航欄。
    
    [[[self addImageView:@"logo" imgName:@"login_logo"] width:170 height:170] relate:LeftTopRight v:290 v2:200 v3:290];
    
    UILabel *title = [[[self addLabel:nil text:@"IT戀" font:48] width:160 height:44] onBottom:@"logo" y:50];
    [[title textColor:@"#000000"] textAlignment:NSTextAlignmentCenter];

    UILabel *description = [[[[self addLabel:nil text:@"找優質靠譜IT男就上IT戀" font:36] width:450 height:34] onBottom:title y:48] toCenter:X];
    [[description textColor:@"#000000"] textAlignment:NSTextAlignmentCenter];
    
    UIButton *regBtn = [[[[self addButton:@"Reg" title:@"立即註冊"] width:287 height:77] onBottom:description y:484] toCenter:X];
    [[regBtn backgroundImage:@"login_btn"] keyValue:@{@"leftNavImage":@"nav_arrow_left_black"}];

    UIButton *loginBtn = [[[[self addButton:@"Login" title:@"已有賬號,立即登錄" font:24] width:300 height:26] onBottom:regBtn y:60] toCenter:X];
    [[loginBtn titleColor:MainHexColor] keyValue:STPreView.keyValue];
}


@end

代碼功能講解(第二點和第三點下麵再細講):

1:基本上一個控制項佈局就一行代碼,直接看過去就好了。

2:第一行設置不需要導航欄,並直接隱藏導航欄:[self needNavigationBar:NO setNavBar:YES];//隱藏導航欄

3:註冊和登陸按鈕,多了一個陌生的keyValue,因為這裡要控制導航的返回按鈕為自定義的圖片。

再看看StartController中的全部代碼:

@interface StartController : STController //StartController.h
@end
@implementation StartController //StartContrller.m -(instancetype)init { //初始化全局設置,必須要在UI初始之前。 [self configNavAndStatusBar]; return self; } -(void)configNavAndStatusBar {
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault animated:YES];//白色底,所以狀態字顏色改為黑
    
    //這裡提前統一設定全局協議的內容(對於登陸、註冊、找回密碼三個窗體有效),進入Main之後,會重新修改全局協議的內容
    [[[[[[UINavigationBar globalSetting] barTintColor:ColorWhite]tintColor:ColorBlack] backgroundImage:nil] shadowImage:nil]
     titleTextAttributes:@{NSForegroundColorAttributeName:ColorBlack}];
}

功能講解:

1:設置全局的導航欄和狀態欄屬性。 

2:如果當前不是導航控制器,則設置自身為導航根控制器。

Sagit 框架講解:佈局

對於框架的佈局:

1:以【self addXXX】為起手勢,一行代碼實現一個UI的佈局。

2:對於需要特定類型的控制屬性的,用變數接收後,用無限連語法處理屬性賦值。

3:相對父控制項,用relate方法;相對同級,用:onTop、onLeft、onRight、onBottom方法,可以混著用,怎麼簡單怎麼來。

佈局的方法,都抽到了以下STUIViewAutoLayout文件中:

看看基本的方法重載:

#pragma mark [相對佈局方法] RelativeLayout
-(UIView*)onRight:(id)uiOrName x:(CGFloat)x;
-(UIView*)onRight:(id)uiOrName x:(CGFloat)x y:(CGFloat)y;
-(UIView*)onLeft:(id)uiOrName x:(CGFloat)x;
-(UIView*)onLeft:(id)uiOrName x:(CGFloat)x y:(CGFloat)y;
-(UIView*)onTop:(id)uiOrName y:(CGFloat)y;
-(UIView*)onTop:(id)uiOrName y:(CGFloat)y x:(CGFloat)x;
-(UIView *)onBottom:(id)uiOrName y:(CGFloat)y;
-(UIView *)onBottom:(id)uiOrName y:(CGFloat)y x:(CGFloat)x;
-(UIView*)relate:(XYLocation)location v:(CGFloat)value;
-(UIView*)relate:(XYLocation)location v:(CGFloat)value v2:(CGFloat)value2;
-(UIView*)relate:(XYLocation)location v:(CGFloat)value v2:(CGFloat)value2 v3:(CGFloat)value3;
-(UIView*)relate:(XYLocation)location v:(CGFloat)value v2:(CGFloat)value2 v3:(CGFloat)value3 v4:(CGFloat)value4;
-(UIView*)toCenter;
-(UIView*)toCenter:(XYFlag)xyFlag;

這個很好理解的,基本讀過去就明白了,簡單易懂,其它的屬性,等後續文章用到再說。

Sagit 框架講解:事件

上一篇文章中,對事件有過一段講解:

框架對於UIView擴展了兩種點擊事件的綁定方式:

#pragma mark 擴展系統事件
-(UIView*)click:(NSString*)event;
- (UIView*)addClick:(onClick)block;

click用於指定一個事件的名稱,addClick用於追加一個事件執行的代碼塊。

也說了事件的定址流程:

1:先找傳進來的event在所在的Controller中是否有對應的事件,若有,執行,若沒有繼續以下:

2:對event追加尾碼變成eventClick和eventClick:再看有沒有對應的事件,若有,執行,若沒有繼續以下:

3:對event追加尾碼變成EventController,看有沒有對應的控制器,若有,執行預設的open:事件跳轉,若沒有,則無綁定事件。

不過上面的佈局代碼中並沒使用click或addClick,同樣是觸發了這個流程:

核心就在於UIButtton的name,如果一個按鈕有name,則尋找事件,如果找到,就自動綁定事件。

因此,對於兩個name,Reg和Login:一路找到最終會找到RegController和LoginController,觸發STController中預先定義的open:事件。

Sagit 框架講解:keyValue屬性和[UINavigationBar globalSetting]

1:keyValue屬性

IT戀這裡有點特殊,跳轉後需要改變導航欄的返回圖標,原來在Controller中寫事件:

[self stPush:方法的第三個參數,指定一張圖片做為返回按鈕]

不過對於有代碼潔P的我,總想著怎麼消滅掉這些這些代碼,雖然兩個事件就幾行,但也不留。

這個參數怎麼傳到open:里呢?如果不是圖片,是指定文字為返回的按鈕呢?

最後想到一個相對完美的解決方案:

1:對UIView再擴展了一個keyValue的屬性,於是有了:

[[regBtn backgroundImage:@"login_btn"] keyValue:@{@"leftNavImage":@"nav_arrow_left_black"}];

2:open:事件中,再進行一下的簡單判斷拿值。

就這樣完美的解決了。

後來發現這個keyValue還有更多的用戶場景,如:設置控制導航欄的顯示或隱藏:

 [self needNavigationBar:NO setNavBar:YES];//隱藏導航欄。

內部其實就是對keyValue進行取值或賦值:

-(UIView*)needNavigationBar:(BOOL)yesNo setNavBar:(BOOL)setNavBar
{
    if(self.keyValue==nil)
    {
        self.keyValue=[NSMutableDictionary new];
    }
    [self.keyValue set:@"needNavigationBar" value:yesNo?@"1":@"0"];
    if(setNavBar && self.STController!=nil && self.STController.navigationController!=nil)
    {
        self.STController.navigationController.navigationBar.hidden=!yesNo;
    }
    return self;
}

目前框架是自動控制導航欄的顯示或隱藏,不需要用戶去再操心的在每個頁面都是寫代碼了。

為了這個導航欄,真花我不少心力,特別是自定義返回和系統滑動返回,研究的過程都夠另外再寫一篇。

2:UINavigationBar globalSetting 的產生:

 A:對於這個StartController這個頁面,有以下幾種情況會跳轉過來:

1:從歡迎引導頁WelcomeController進來;

2:用戶進行系統後,點擊退出時從SystemController進來;

3:當前用戶的Token數據失效,需要重新登陸時,從MainController中,跳進來;

不管從哪個地方過來,由於自身需要占根視圖,而為導航控制器,所以有一行代碼:

//從引導頁跳轉來時,需要將自身設置為導航根控制器
 if(self.STController.navigationController==nil){[self.STController asRoot:RootViewNavigationType];}

框架對UIViewCtroller擴展了:asRoot方法,可以將當前Controller直接設置為根視圖:

//將當前視圖設置為根視圖
-(UIViewController*)asRoot:(RootViewControllerType)rootViewControllerType{
    
    UIViewController *controller=self;
    if(rootViewControllerType==RootViewNavigationType)
    {
        controller = [[UINavigationController alloc]initWithRootViewController:self];
        //self.navigationController.navigationBar.hidden=!self.view.needNavigationBar;
    }
    [UIApplication sharedApplication].delegate.window.rootViewController=controller;
    return self;
}

B:導航欄進行統一的顏色風格處理(處理後,將對註冊、登陸、找回密碼等生效):

之前的代碼是這樣的:

框架封裝完成屬性無限連後可以這樣:

[[[[[[UINavigationBar globalSetting] barTintColor:ColorWhite]tintColor:ColorBlack] backgroundImage:nil] shadowImage:nil]
     titleTextAttributes:@{NSForegroundColorAttributeName:ColorBlack}];

這裡有幾點坑和大伙分享:

坑A:如何進行屬性無限連

[UINavigationBar appearance] 這裡返回的是協議介面,並不是UINavigationBar實例

一開始看到UINavigationBar去接收appearance的屬性,聰明如我,就去擴展UINavigationBar的屬性方法,然後打算用無限連簡化。

結果一運行就死,進入坑裡徘徊了不少時間,最後才發現appearance返回的是UIAppearance介面,並不是UINavigationBar類型。

但是UIAppearnce又不能直接用,也不能對協議介面做擴展,一時蒙了下B。

然後繞到導航欄顯示不顯示、自定義返回和滑動返回,返回主界面沒主動往上頂等坑裡。

坑裡呆久出來後,想到另一種方式來實現無限連:

通過一個靜態方法返回一個自定義類,再由這個自定義類來連代碼,像這樣:

@implementation UINavigationBar (ST)

+(UINavigationBarSetting*)globalSetting
{
    return [UINavigationBarSetting new];
}
@end

@implementation UINavigationBarSetting
#pragma mark 擴展系統屬性
-(UINavigationBarSetting*)tintColor:(id)colorOrHex
{
    [UINavigationBar appearance].tintColor=[UIView toColor:(colorOrHex)];
    return self;
}
-(UINavigationBarSetting*)barTintColor:(id)colorOrHex
{
    [UINavigationBar appearance].barTintColor=[UIView toColor:(colorOrHex)];
    return self;
}

坑B:為何全局設置無效

以前的代碼,先執行ViewDidLoad里的全局設置,再執行asRoot,觸發導航欄,這樣是正常的:

-(void)viewWillAppear:(BOOL)animated
{
    if(self.navigationController==nil)
    {
        [self asRoot:RootViewNavigationType];
        //self.navigationController.navigationBar.hidden = YES;
    }
}

但是這段代碼被我消滅了,其它地方的跳轉代碼都是直接,退出後轉跳:

改完後,發現全局失效了,最後坑裡呆了一圈才發現:

全局的設置,必須在導航欄UI出現之前設置才有效,所以,如果這樣寫代碼:

全局設置就不能寫在ViewDidLoad里了,必須寫在init中了。

總結:

1:用框架寫代碼很簡單,也很簡潔。

2:框架目前的代碼不多,早看早了結。

3:隨著應用場景的增多,框架會不斷的增強,預味著開發仍是很簡單,但要理解原理就需要花更多時間。

4:雖然教程是以IT戀為講解,但還是希望大伙多關心IT連,哈。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一,一般,購買內容包括內容類型,功能擴展,服務和訂閱。 二,測試環境搭建: 搭建測試環境比較麻煩,需要使用2個工具管理:iTunes Connect和iOS開發中心的配置門戶網站。 三,提交給App Store數據結構只能是NSSet集合,集合中的元素是產品標識字元串。 四,base64forDat ...
  • 如題,今天的博客我們就來記錄一下iOS開發中使用MachPort來實現線程間的通信,然後使用該知識點來轉發子線程中所發出的Notification。簡單的說,MachPort的工作方式其實是將NSMachPort的對象添加到一個線程所對應的RunLoop中,並給NSMachPort對象設置相應的代理 ...
  • bounds/frame/center/transform的解釋以及相對關係 ...
  • 代碼已經分享至github:https://github.com/YanYoJun/NavigationDemo 轉載請註明原文鏈接:http://www.cnblogs.com/yanyojun/p/8076015.html 一、直接看佈局 額,其實就這麼點東西,其他也沒有什麼,在DrawerLa ...
  • Request經常都要攜帶Cookie,上面說過request創建時可以通過header設置參數,Cookie也是參數之一。就像下麵這樣: 然後可以從返回的response里得到新的Cookie,你可能得想辦法把Cookie保存起來。但是OkHttp可以不用我們管理Cookie,自動攜帶,保存和更新 ...
  • Try this, it fixed it for me. Open Terminal and run: cd ~ mv .itmstransporter/ .old_itmstransporter/ "/Applications/Xcode.app/Contents/Applications/Ap... ...
  • 引言 Service服務是Android四大組件之一,在Android中有著舉足重輕的作用。Service服務是工作的UI線程中,當你的應用需要下載一個文件或者播放音樂等長期處於後臺工作而有沒有UI界面的時候,你肯定要用到Service+Thread來實現。因此你需要自己在Service服務裡面實現 ...
  • 1、ADB是什麼? ADB,即Android Debug Bridge,它是Android提供的一個通用的調試工具。藉助這個工具可以很好的調試開發程式。它是客戶端/服務端架構的命令工具,主要分三個部分: (1)adb客戶端:運行在我們的開發機器上 (2)adb 伺服器:在開發機器後臺運行的進程 (3 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...