多控制器-2

筆記

0_1.jpg
0_1.jpg
1_1.jpg
2_1.jpg
3_1.jpg
05-KVC模型改進-自定義國旗鍵盤.jpg
06-自定義生日鍵盤.jpg
07-自定義城市鍵盤.jpg
08-自定義城市鍵盤-初始化文字處理-.jpg
09-導航控制器簡介.jpg
10-導航控制器View的結構.jpg
11-導航控制器的使用.jpg
12-導航控制器管理原則.jpg
13-設置導航條內容.jpg

Xmind

中心主題.png

PPT

1-控制器管理

  • 控制器以及view的多種創建方式
  • UINavigationController的簡單使用:添加\移除子控制器
  • UINavigationBar內容的設置
  • 控制器的生命周期方法
  • Segue的使用
  • 控制器之間數據的傳遞
  • UITabBarController的簡單使用
  • UITabBarController和UINavigationController的混合使用
  • Modal

2-創建控制器

控制器常見的創建方式有以下幾種

  • 直接創建
MJViewController *mj = [[MJViewController alloc] init];
  • 指定xib文件來創建
MJViewController *mj = [[MJViewController alloc] initWithNibName:@"MJViewController" bundle:nil];
  • 通過storyboard創建
    • 先加載storyboard文件(Test是storyboard的文件名)
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Test" bundle:nil];
  • 接著初始化storyboard中的控制器(兩種方式)
    • 初始化“初始控制器”(箭頭所指的控制器)
MJViewController *mj = [storyboard instantiateInitialViewController];
   - 通過一個標識初始化對應的控制器
MJViewController *mj = [storyboard instantiateViewControllerWithIdentifier:@”mj"];

3-控制器的View

Snip20170213_196.png
  • 控制器view的延遲加載
  • 控制器的view是延遲加載的:用到時再加載
  • 可以用isViewLoaded方法判斷一個UIViewController的view是否已經被加載
  • 控制器的view加載完畢就會調用viewDidLoad方法

4-多控制器的管理

  • 一個iOS的app很少只由一個控制器組成,除非這個app極其簡單
  • 當app中有多個控制器的時候,我們就需要對這些控制器進行管理
  • 有多個view時,可以用一個大的view去管理1個或者多個小view
  • 控制器也是如此,用1個控制器去管理其他多個控制器
  • 比如,用一個控制器A去管理3個控制器B、C、D
    • 控制器A被稱為控制器B、C、D的“父控制器”
    • 控制器B、C、D的被稱為控制器A的“子控制器”
  • 為了便于管理控制器,iOS提供了2個比較特殊的控制器
    • UINavigationController
    • UITabBarController

5-UINavigationController

UINavigationController的view結構

Snip20170213_197.png
Snip20170213_199.png

UINavigationController的簡單使用

  • UINavigationController的使用步驟
    • 初始化UINavigationController
    • 設置UIWindow的rootViewController為UINavigationController
    • 根據具體情況,通過push方法添加對應個數的子控制器


      Snip20170213_200.png

UINavigationController的子控制器

  • UINavigationController以棧的形式保存子控制器
    • @property(nonatomic,copy) NSArray *viewControllers;
  • @property(nonatomic,readonly) NSArray *childViewControllers;
  • 使用push方法能將某個控制器壓入棧
     -(void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated;
    
- 使用pop方法可以移除控制器
   - 將棧頂的控制器移除

-(UIViewController *)popViewControllerAnimated:(BOOL)animated;

   - 回到指定的子控制器
  • (NSArray *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated;
   - 回到根控制器(棧底控制器)

-(NSArray *)popToRootViewControllerAnimated:(BOOL)animated;


###如何修改導航欄的內容
 - 導航欄的內容由棧頂控制器的navigationItem屬性決定
 - UINavigationItem有以下屬性影響著導航欄的內容
     - 左上角的返回按鈕

@property(nonatomic,retain) UIBarButtonItem *backBarButtonItem;

     - 中間的標題視圖

@property(nonatomic,retain) UIView *titleView;

     - 中間的標題文字

@property(nonatomic,copy) NSString *title;

     - 左上角的視圖

@property(nonatomic,retain) UIBarButtonItem *leftBarButtonItem;
UIBarButtonItem *rightBarButtonItem 右上角的視圖
@property(nonatomic,retain) UIBarButtonItem *rightBarButtonItem;


##6-Segue
- Storyboard上每一根用來界面跳轉的線,都是一個UIStoryboardSegue對象(簡稱Segue)
![Snip20170213_201.png](http://upload-images.jianshu.io/upload_images/1609505-3118d2cb7d70cd51.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

###Segue的屬性
- 每一個Segue對象,都有3個屬性
  - 唯一標識

@property (nonatomic, readonly) NSString *identifier;

 - 來源控制器

@property (nonatomic, readonly) id sourceViewController;

 - 目標控制器

@property (nonatomic, readonly) id destinationViewController;

![Snip20170213_202.png](http://upload-images.jianshu.io/upload_images/1609505-352866aea0422f63.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

###Segue的類型
- 根據Segue的執行(跳轉)時刻,Segue可以分為2大類型
  - 自動型:點擊某個控件后(比如按鈕),自動執行Segue,自動完成界面跳轉
 - 手動型:需要通過寫代碼手動執行Segue,才能完成界面跳轉

###自動型Segue
- 按住Control鍵,直接從控件拖線到目標控制器
![Snip20170213_203.png](http://upload-images.jianshu.io/upload_images/1609505-249c5a6f9c9c54c4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
- 點擊“登錄”按鈕后,就會自動跳轉到右邊的控制器
- 如果點擊某個控件后,不需要做任何判斷,一定要跳轉到下一個界面,建議使用“自動型Segue”

###手動型Segue
- 按住Control鍵,從來源控制器拖線到目標控制器
![Snip20170213_204.png](http://upload-images.jianshu.io/upload_images/1609505-892d8d8d07212308.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
- 在恰當的時刻,使用perform方法執行對應的Segue

[self performSegueWithIdentifier:@"login2contacts" sender:nil];
// Segue必須由來源控制器來執行,也就是說,這個perform方法必須由來源控制器來調用

- 如果點擊某個控件后,需要做一些判斷,也就是說:滿足一定條件后才跳轉到下一個界面,建議使用“手動型Segue”

###performSegueWithIdentifier:sender:方法
- 利用performSegueWithIdentifier:方法可以執行某個Segue,完成界面跳轉
- 接下來研究performSegueWithIdentifier:sender:方法的完整執行過程
[self performSegueWithIdentifier:@“login2contacts” sender:nil];
// 這個self是來源控制器
 - 根據identifier去storyboard中找到對應的線,新建UIStoryboardSegue對象
   - 設置Segue對象的sourceViewController(來源控制器)
   - 新建并且設置Segue對象的destinationViewController(目標控制器)
![Snip20170213_205.png](http://upload-images.jianshu.io/upload_images/1609505-e9e451f60894d6ca.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
 - 調用sourceViewController的下面方法,做一些跳轉前的準備工作并且傳入創建好的Segue對象
  • (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender;
    // 這個sender是當初performSegueWithIdentifier:sender:中傳入的sender
 - 調用Segue對象的- (void)perform;方法開始執行界面跳轉操作
    - 如果segue的style是push
         - 取得sourceViewController所在的UINavigationController
         - 調用UINavigationController的push方法將destinationViewController壓入棧中,完成跳轉
   - 如果segue的style是modal
        - 調用sourceViewController的presentViewController方法將destinationViewController展示出來

###Sender參數的傳遞

[self performSegueWithIdentifier:@“login2contacts” sender:@“jack”];

  • (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender;

##7-控制器的數據傳遞
- 控制器之間的數據傳遞主要有2種情況:順傳和逆傳
   - 順傳
       - 控制器的跳轉方向: A->C
       - 數據的傳遞方向    : A -> C
       - 數據的傳遞方式    :  在A的prepareForSegue:sender:方法中根據segue參數取得destinationViewController, 也就是控制器C, 直接給控制器C傳遞數據
(要在C的viewDidLoad方法中取得數據,來賦值給界面上的UI控件)
![Snip20170213_206.png](http://upload-images.jianshu.io/upload_images/1609505-54f54004954ecffa.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
   - 逆傳
       - 控制器的跳轉方向: A ->C
       - 數據的傳遞方向    : C ->A
       - 數據的傳遞方式    :  讓A成為C的代理, 在C中調用A的代理方法,通過代理方法的參數傳遞數據給A
![Snip20170213_207.png](http://upload-images.jianshu.io/upload_images/1609505-6627469cc74c3cdb.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

##8-UITabBarController
###UITabBarController的簡單使用
- UITabBarController的使用步驟
   - 初始化UITabBarController
   - 設置UIWindow的rootViewController為UITabBarController
   - 根據具體情況,通過addChildViewController方法添加對應個數的子控制器

###UITabBarController的子控制器
- UITabBarController添加控制器的方式有2種
   - 添加單個子控制器
- (void)addChildViewController:(UIViewController *)childController;

  - 設置子控制器數組

@property(nonatomic,copy) NSArray *viewControllers;


###UITabBarController的view結構
![Snip20170213_208.png](http://upload-images.jianshu.io/upload_images/1609505-4f545988d072bdf8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

![Snip20170213_209.png](http://upload-images.jianshu.io/upload_images/1609505-4c426df4a432b08f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

###UITabBar
- 如果UITabBarController有N個子控制器,那么UITabBar內部就會有N個UITabBarButton作為子控件
- 如果UITabBarController有4個子控制器,那么UITabBar的結構大致如下圖所示
![Snip20170213_210.png](http://upload-images.jianshu.io/upload_images/1609505-715ec44decd224aa.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

###UITabBarButton
![Snip20170213_211.png](http://upload-images.jianshu.io/upload_images/1609505-05c4840455efa8f4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

###App主流UI框架結構
![Snip20170213_212.png](http://upload-images.jianshu.io/upload_images/1609505-32a56168578f76c1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

###Modal
- 除了push之外,還有另外一種控制器的切換方式,那就是Modal
- 任何控制器都能通過Modal的形式展示出來
- Modal的默認效果:新控制器從屏幕的最底部往上鉆,直到蓋住之前的控制器為止
- 以Modal的形式展示控制器
  • (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^)(void))completion
- 關閉當初Modal出來的控制器
  • (void)dismissViewControllerAnimated: (BOOL)flag completion: (void (^)(void))completion;
![Snip20170213_213.png](http://upload-images.jianshu.io/upload_images/1609505-e89d68e15fa388d4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

###9-圖片
![控制器view加載.png](http://upload-images.jianshu.io/upload_images/1609505-5bafac4a1e751f6f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

![內存警告處理.png](http://upload-images.jianshu.io/upload_images/1609505-f989f56d665128f5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

![生命周期方法.png](http://upload-images.jianshu.io/upload_images/1609505-ddf7ebcfa8ea0eae.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

#總結

1.loadView方法作用以及注意點有哪些?
作用:控制器會調用方法去創建控制器的View.
什么時候調用:當第一次使用控制器的View
開發中loadView使用場景:自定義控制器的View.
1.一旦重寫了loadView,表示需要自己創建控制器的View.
2.如果控制器的View還沒有賦值,就不能調用控制器View的get方法.會造成死循環.因為控制器View的get方法底層會調用loadView方法.

2.KVC底層實現?
setValue:obj forKeyPath:key的底層實現:
1.它會調用這個屬性的set方法.
2.如果沒有set方法,它會去判斷有沒有跟key值同名的成員屬性.如果有,就直接賦值.icon = obj.
3.如果沒有,那么它還會去判斷有沒有跟key值名相同帶有下劃線的成員屬性,如果有,就直接賦值,_icon = obj.
4.如果都沒有, 就直接報錯.找不到對應的成員屬性.

3.控制器View懶加載是什么意思?
什么時候用到控制器View的時候,才會調用loadView方法創建控制器的View

4.導航控制器管理原則?
1.當調用導航控制器的push方法時, 就會把一個控制器壓入到導航控制器的棧中, 那么剛壓入棧中的這個導航控制器就在棧的最頂部.
2.它就會把原來導航控制器View當中存放的子控制器View的內容移除,然后把導航控制器棧頂控制器的View添加到導航控制器專門存放子控制器View當中.
3.注意:只是把控制器的View從導航控制器存放子控制器的View當中移除,并沒有把控制器從棧中移除.所以上一個控制器還在.
4.當調用pop當方法時, 就會把導航控制器存放子控制器View當中控制器的View移除,并且會把該控制器從棧里面移除.
5.此時該控制器就會被銷毀.接著它就會把上一個控制器的View添加到導航控制器專門存放子控制器的View當中.

5.如果設置導航條內容?
設置導航條的內容,由棧頂控制器的NavgationItem決定.

6.事件是怎么樣產生與傳遞的?
1.當發生一個觸摸事件后,系統會將該事件加入到一個由UIApplication管理的事件隊列中.
2.UIApplication會從事件隊列中取出最前面的事件,將事件傳遞給主窗口
3.主窗口會在視圖層次結構中找到一個最合適的視圖來處理觸摸事件
4.觸摸事件的傳遞是從父控件傳遞到子控件的.
5.如果一個父控件不能接收事件,那么它里面的了子控件也不能夠接收事件.

7.一個控件什么情況下不能夠接收事件?
1.不接收用戶交互時不能夠處理事件:userInteractionEnabled = NO
2.當一個控件隱藏的時候不能夠接收事件:Hidden = YES的時候
3.當一個控件為透明白時候也不能夠接收事件:alpha <= 0.01

8.如果尋找最適合的View?
1.先判斷自己是否能夠接收觸摸事件,如果能再繼續往下判斷,
2.再判斷觸摸的當前點在不在自己的身上.
3.如果在自己身上,它會從后往前遍歷子控件,遍歷出每一個子控件后,重復前面的兩個步驟.
4.如果沒有符合條件的子控件,那么它自己就是最適合的View.

9.事件傳遞與響應的完整過程是什么?
1.先將事件對象由上往下傳遞(由父控件傳遞給子控件),找到最合適的控件來處理這個事件。
2.調用最合適控件的touches….方法
3.如果調用了[super touches….];就會將事件順著響應者鏈條往上傳遞,傳遞給上一個響應者
4.接著就會調用上一個響應者的touches….方法

10.如何判斷上一個響應者
1.如果當前這個view是控制器的view,那么控制器就是上一個響應者
2.如果當前這個view不是控制器的view,那么父控件就是上一個響應者

11.UIApplication作用?
1.設置應用提醒數字
2.設置連網狀態
3.設置狀態欄
4.跳轉網頁

12.應用程序的程動原理
1.執行Main
2.執行UIApplicationMain函數.
3.創建UIApplication對象,并設置UIApplicationMain對象的代理.
4.開啟一個主運行循環.保證應用程序不退出.
5.加載info.plist.加載配置文件.判斷一下info.plist文件當中有沒有Main storyboard file base name,里面有沒有指定storyboard文件,

13.如何創建UIWindow?
1.創建窗口
2.創建控制器
3.設置控制器為窗口的根控制器
4.顯示窗口

14.push與show的區別(push與show方法只有在有導航控制器下才有效)
1.push這個方法過期了,通過StoryBoard跳轉控制器,從一個控制器的界面按住ctrl拖向下一個控制器,運行時可以從當前控制器跳轉到下一個控制器。
2.show方法也是一樣,功能相同但他是個新方法,在iphone設備上show顯示的是一個控制器窗口,但在ipad的上顯示的是兩個窗口,一個正常窗口一個是詳情頁窗口。
3.-viewDidLoad方法在view的整個生命周期中只會調用一次,所以在這個方法里面可以加載子控件和加載網絡數據請求
4.-viewWillAppear和-viewWillDisAppear方法里面設置view即將顯示時和即將消失時需要設置的操作,這兩個方法多次調用

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

推薦閱讀更多精彩內容