UI控件進(jìn)階2——多控制器管理


控制器及View的多種創(chuàng)建方式

  • 創(chuàng)建控制器的3種方式?
    1. 直接通過alloc + init的方式創(chuàng)建。
      • 創(chuàng)建一個“Single View Application”,刪除默認(rèn)控制器、Main.storyboard、Main Interface設(shè)置為空。
      • 創(chuàng)意一個自定義的控制器,F(xiàn)irstViewController。
      • 在AppDelegate的application:didFinishLaunchingWithOptions:方法中創(chuàng)建UIWindow對象。
      • 通過alloc + init的方式創(chuàng)建該控制器的對象,并設(shè)置該控制器view的背景色。
      • 設(shè)置UIWindow的根控制器為該控制器對象。
    2. 通過加載storyboard文件來創(chuàng)建一個控制器。
      • 刪除了Main.storyboard文件,也清空了Main Interface的配置,那么現(xiàn)在就需要自己創(chuàng)建一個新的storyboard文件(Two.storyboard), 然后拖一個控制器上去,在AppDelegate中自己寫代碼來加載Two.storyboard文件。
    3. 通過指定的xib文件來創(chuàng)建控制器。
      • 創(chuàng)建一個自己的控制器類。
      • 創(chuàng)建一個xib文件,在xib文件中拽一個UIView。
      • 選中xib文件中的“File's Owner”,在屬性中設(shè)置對應(yīng)的類(Class)是剛才創(chuàng)建的控制器類。“File's Owner”可以理解為,當(dāng)前xib文件是為誰服務(wù)的。
      • 然后選中“File's Owner”->“右擊”選中“view”->拖線到對應(yīng)的view上。(設(shè)置該xib文件中哪個視圖是控制器默認(rèn)要創(chuàng)建的視圖)
      • 通過alloc + initWithNibName來創(chuàng)建。
// 一、直接通過alloc+init的方式創(chuàng)建
// 1.創(chuàng)建UIWindow
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
// 2.創(chuàng)建控制器 
FirstViewController *vc1 = [[FirstViewController alloc] init];
vc1.view.backgroundColor = [UIColor blueColor];
// 3.設(shè)置控制器為UIWindow對象的根控器"rootViewController"                            
self.window.rootViewController = vc1;
// 4.顯示UIWindow對象
[self.window makeKeyAndVisible];

// 二、通過加載storyboard文件創(chuàng)建
// 1.加載對應(yīng)的storyboard文件
UIStoryboard *myStoryboard = [UIStoryboard storyboardWithName:@"My" bundle:nil];
// 2.創(chuàng)建該storyboard中的被設(shè)置為"初始化控制器"(箭頭所指向的控制器)的對象。
UIViewController *vc2 = [myStoryboard instantiateInitialViewController];
// 3.根據(jù)storyboard中的控制器的storyboard ID來創(chuàng)建對應(yīng)的控制器
UIViewController *vc3 = [myStoryboard instantiateViewControllerWithIdentifier:@"redVwController"];
// 4.設(shè)置控制器為UIWindow對象的根控制器"rootViewController"
self.window.rootViewController = vc2;

// 三、通過指定的 xib 文件來創(chuàng)建
// 1.通過xib文件, 創(chuàng)建控制器
FirstViewController *vc1 = [[FirstViewController alloc] initWithNibName:@"First" bundle:nil];
// 2.設(shè)置控制器為UIWindow對象的根控制器"rootViewController"
self.window.rootViewController = vc1;

  • 創(chuàng)建控制器中的UIView?
    1. 控制器創(chuàng)建好以后,控制器所管理的view是如何創(chuàng)建的?
      • 控制器的view是通過調(diào)用控制器的loadView方法來創(chuàng)建的。這個方法是UIViewController中的一個對象方法,只要控制器的loadView方法被調(diào)用了,那么證明控制器的view創(chuàng)建好了。
      • 當(dāng)調(diào)用完畢控制器的loadView方法以后,從這時開始,才創(chuàng)建好了控制器的view。
      • 當(dāng)控制器的view被創(chuàng)建好以后,緊接著就調(diào)用控制器的viewDidLoad方法。
      • 控制器的view采用了懶加載的方式,也就是說,在需要的時候(在用到的時候)才會創(chuàng)建(調(diào)用loadView方法)。
      • 注意:無論控制器是如何創(chuàng)建的,只要在控制器中,重寫了loadView方法,并且沒有調(diào)用[super loadView];方法,那么最終控制器的view就必須完全在loadView方法中自己來創(chuàng)建了,所以loadView方法可以用來自定義view。
    2. 控制器中的view創(chuàng)建:當(dāng)?shù)谝淮螐膕elf.view中獲取view的時候(第一次使用self.view的時候),控制器會調(diào)用它自己的loadView方法先創(chuàng)建一個view,并且把這個新創(chuàng)建的view設(shè)置給self.view。
      • 如果是直接通過alloc + init方法創(chuàng)建的控制器,則self.view = [[UIView alloc] init];。
      • 如果是通過storyboard創(chuàng)建的控制器,加載storyboard中的控制器,并把storyboard中的控制器中的view設(shè)置給self.view。
      • 如果是通過加載xib創(chuàng)建的控制器,加載xib中的view,并把xib中的view設(shè)置給self.view。
    3. 通過storyboard創(chuàng)建完控制器后,自動調(diào)用loadView方法,創(chuàng)建控制器的view。此時自定義的控制器,因為沒有“重寫”loadView方法,所以loadView方法內(nèi)部就是根據(jù)storyboard文件中的view來創(chuàng)建view的。
    4. 通過xib文件創(chuàng)建完控制器后,自動調(diào)用loadView創(chuàng)建控制器的view。此時自定義的控制器,因為沒有“重寫”loadView方法,所以loadView方法內(nèi)部就是根據(jù)xib文件中的view來創(chuàng)建view的。
      • 如果創(chuàng)建控制器的時候,通過initWithNibName指定了xib的名字,那么就根據(jù)該xib創(chuàng)建view。
      • 如果創(chuàng)建控制器的時候,沒有指定任何xib文件,也沒有相應(yīng)的storyboard文件,那么會嘗試查找“與控制器名字相同的,但是去除Controller的文件名的xib文件”,如果還是沒有,會嘗試查找與控制器名字完全相同的xib文件,如果有,則使用該xib文件創(chuàng)建view。
      • 建議:如果要使用某個xib文件名自動匹配的方式創(chuàng)建view,建議名字與控制器相同。
    5. 通過重寫UIViewController的loadView方法,自己通過代碼來創(chuàng)建控制器的view。
      • 控制器的loadView方法就是用來自定義view的。如果要為控制器自定義view,要寫在loadView中,不要寫在viewDidLoad中。
      • 如果重寫loadView方法中調(diào)用了[super loadView];,那么依然會使用默認(rèn)的方式來加載。想自定義,應(yīng)該不調(diào)用此方法。
    6. 無論是通過加載xib創(chuàng)建view,storyboard創(chuàng)建view,最終都依賴于loadView方法。
    7. 控制器的loadView方法什么時候調(diào)用?
      • 在需要用到控制器的view的時候才調(diào)用,當(dāng)調(diào)用UIWindow對象的makeKeyAndVisible方法時,就需要顯示該view了,此時就表示用到view了,這個就叫做“延遲加載”。

多控制器管理

  • 多控制器管理?
    1. 多控制器管理的思路:使用一個控制器來管理所有其他控制器,類似于使用一個UIView來管理其他的子view。
    2. 父控制器:管理其他控制器的控制器,就可以看做是“父控制器”、子控制器:被管理的控制器就是子控制器。
    3. iOS提供了兩個比較特殊的控制器(用來管理“控制器”的控制器):
      • UINavigationController導(dǎo)航控制器,輕松管理多個控制器,并且控制不同控制器之間的跳轉(zhuǎn)和切換。
      • UITabBarController也可以輕松地管理多個控制器,輕松完成控制器之間的切換。

  • UINavigationController導(dǎo)航控制器?
    1. 使用步驟:
      • 創(chuàng)建、初始化一個導(dǎo)航控制器:UINavigationController。
      • 設(shè)置UIWindow的rootController為UINavigationController。
      • 通過調(diào)用push方法添加子控制器到UINavigationController。
      • 通過pop方法可以返回到上一個控制器。
      • 注意:誰是最后一個push進(jìn)來的,當(dāng)前顯示的就是哪個viewController。
    2. 導(dǎo)航控制器的導(dǎo)航欄是從Y坐標(biāo)20開始的,高度是44,導(dǎo)航欄上面的20高度是“狀態(tài)欄”。導(dǎo)航欄的內(nèi)容由棧頂控制器的navigationItem屬性決定。
    3. UINavigationController導(dǎo)航控制器以棧的形式保存的子控制器。
@property(nonatomic,copy) NSArray *viewControllers;
@property(nonatomic,readonly) NSArray *childViewControllers;
// 使用push方法能將某個控制器壓入棧
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated;

// 使用pop方法可以移除棧頂控制器
// 將棧頂?shù)目刂破饕瞥?- (UIViewController *)popViewControllerAnimated:(BOOL)animated;
// 回到指定的子控制器
- (NSArray *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated;
// 回到根控制器(棧底控制器)
- (NSArray *)popToRootViewControllerAnimated:(BOOL)animated;

// 左上角的返回按鈕
@property(nonatomic,retain) UIBarButtonItem *backBarButtonItem;
// 中間的標(biāo)題視圖
@property(nonatomic,retain) UIView *titleView;
// 中間的標(biāo)題文字
@property(nonatomic,copy) NSString *title;
// 左上角的按鈕
@property(nonatomic,retain) UIBarButtonItem *leftBarButtonItem;
// 右上角的按鈕
@property(nonatomic,retain) UIBarButtonItem *rightBarButtonItem;

  • UITabBarController?
    1. 使用步驟:
      • 初始化UITabBarController。
      • 設(shè)置UIWindow的rootViewController為UITabBarController。
      • 根據(jù)具體情況,通過addChildViewController方法添加對應(yīng)個數(shù)的子控制器。
    2. 如果UITabBarController有N個子控制器,那么UITabBar內(nèi)部就會有N個UITabBarButton作為子控件。
// 添加單個子控制器
- (void)addChildViewController:(UIViewController *)childController;
// 設(shè)置子控制器數(shù)組
@property (nonatomic,copy) NSArray *viewControllers;
// 標(biāo)題文字
@property(nonatomic,copy) NSString *title;
// 圖標(biāo)
@property(nonatomic,retain) UIImage *image;
// 選中時的圖標(biāo)
@property(nonatomic,retain) UIImage *selectedImage;
// 提醒數(shù)字
@property(nonatomic,copy) NSString *badgeValue;


  • App主流UI框架結(jié)構(gòu)?
App主流UI框架結(jié)構(gòu)

  • Segue的介紹?
    1. storyboard上每一根用來界面跳轉(zhuǎn)的線,都是一個UIStoryboardSegue對象,簡稱Segue,表示延續(xù)、繼續(xù)的意思。
    2. 每一個segue對象,都有3個屬性:①唯一標(biāo)識;②來源控制器;③目標(biāo)控制器。
    3. 根據(jù)segue的執(zhí)行(跳轉(zhuǎn))時刻,segue可以分為2大類型:
      • 自動型:點(diǎn)擊某個控件后,自動執(zhí)行segue,自動完成界面跳轉(zhuǎn)。
      • 手動型:需要通過寫代碼手動執(zhí)行segue,才能完成界面跳轉(zhuǎn)。
    4. 自動型segue:
      • 按住control鍵,直接從控件拖線到目標(biāo)控制器。
      • 如果點(diǎn)擊某個控件,不需要做任何判斷,直接跳轉(zhuǎn)到下一個界面,建議使用“自動型segue”。
    5. 手動型segue:
      • 按住control鍵,從來源控制器拖線到目標(biāo)控制器。
      • 手動型的segue需要設(shè)置一個標(biāo)識Identifier。
      • 如果點(diǎn)擊某個控件,需要做一些處理之后才能跳轉(zhuǎn)到下一個界面,建議使用“手動型segue”。
    6. 利用某個控制器的performSegueWithIdentifier:對象方法可以執(zhí)行當(dāng)前控制器的某個Segue,跳轉(zhuǎn)界面:
      • self是來源控制器,只能通過來源控制器來調(diào)用該方法。
      • 根據(jù)Identifier去storyboard中找到對應(yīng)的線,新建UIStoryboardSegue對象。
      • 設(shè)置Segue對象的sourceViewController(來源控制器)。
      • 新建并且設(shè)置Segue對象的destinationViewController(目標(biāo)控制器)。
    7. 調(diào)用sourceViewController來源控制器的- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender;方法,做跳轉(zhuǎn)前的準(zhǔn)備工作并傳入創(chuàng)建好的Segue對象。
      • sender就是調(diào)用performSegueWithIdentifier:sender:方法時傳入的對象。
      • 調(diào)用Segue對象的- (void)perform;方法開始執(zhí)行界面跳轉(zhuǎn)操作。
      • 如果Segue的style是push,則取得sourceViewController所在的UINavigationController,調(diào)用UINavigationController的push方法將destinationViewController壓入棧中,完成跳轉(zhuǎn)。
      • 如果Segue的style是modal調(diào)用sourceViewController的presentViewController方法將destinationViewController展示出來。

  • Modal介紹?
    1. 除了push之外,還有另一種控制器的切換方式,那就是Modal,任何控制器都能通過modal的形式展示出來。
    2. modal的默認(rèn)效果:新控制器從屏幕的最底部往上鉆,直到蓋住之前的控制器為止。
// 以modal的形式展示控制器
- (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^)(void))completion;
// 關(guān)閉當(dāng)初modal出來的控制器
- (void)dismissViewControllerAnimated: (BOOL)flag completion: (void (^)(void))completion;

  • 控制器的數(shù)據(jù)傳遞
    1. 順傳:
      • 控制器的跳轉(zhuǎn)方向:A->B。
      • 數(shù)據(jù)的傳遞方向:A->B。
      • 數(shù)據(jù)的傳遞方式:在A控制器的prepareForSegue:sender:方法中根據(jù)Segue參數(shù)取得destinationViewController,也就是控制器B,直接給控制器B傳遞數(shù)據(jù)。
      • 在B的viewDidLoad方法中取得數(shù)據(jù),或者利用setter方法,設(shè)置界面上的UI控件。
        控制器的數(shù)據(jù)傳遞(順傳)
    2. 逆?zhèn)鳎?
      • 控制器的跳轉(zhuǎn)方向:A->B。
      • 數(shù)據(jù)的傳遞方向:B->A。
      • 數(shù)據(jù)的傳遞方式:讓A成為B的代理,在B中調(diào)用A的代理方法,通過代理方法的參數(shù)傳遞數(shù)據(jù)給A。


        控制器的數(shù)據(jù)傳遞(逆?zhèn)?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容