筆記
Xmind
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
- 控制器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結構
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)

###Segue的屬性
- 每一個Segue對象,都有3個屬性
- 唯一標識
@property (nonatomic, readonly) NSString *identifier;
- 來源控制器
@property (nonatomic, readonly) id sourceViewController;
- 目標控制器
@property (nonatomic, readonly) id destinationViewController;

###Segue的類型
- 根據Segue的執行(跳轉)時刻,Segue可以分為2大類型
- 自動型:點擊某個控件后(比如按鈕),自動執行Segue,自動完成界面跳轉
- 手動型:需要通過寫代碼手動執行Segue,才能完成界面跳轉
###自動型Segue
- 按住Control鍵,直接從控件拖線到目標控制器

- 點擊“登錄”按鈕后,就會自動跳轉到右邊的控制器
- 如果點擊某個控件后,不需要做任何判斷,一定要跳轉到下一個界面,建議使用“自動型Segue”
###手動型Segue
- 按住Control鍵,從來源控制器拖線到目標控制器

- 在恰當的時刻,使用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(目標控制器)

- 調用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控件)

- 逆傳
- 控制器的跳轉方向: A ->C
- 數據的傳遞方向 : C ->A
- 數據的傳遞方式 : 讓A成為C的代理, 在C中調用A的代理方法,通過代理方法的參數傳遞數據給A

##8-UITabBarController
###UITabBarController的簡單使用
- UITabBarController的使用步驟
- 初始化UITabBarController
- 設置UIWindow的rootViewController為UITabBarController
- 根據具體情況,通過addChildViewController方法添加對應個數的子控制器
###UITabBarController的子控制器
- UITabBarController添加控制器的方式有2種
- 添加單個子控制器
- (void)addChildViewController:(UIViewController *)childController;
- 設置子控制器數組
@property(nonatomic,copy) NSArray *viewControllers;
###UITabBarController的view結構


###UITabBar
- 如果UITabBarController有N個子控制器,那么UITabBar內部就會有N個UITabBarButton作為子控件
- 如果UITabBarController有4個子控制器,那么UITabBar的結構大致如下圖所示

###UITabBarButton

###App主流UI框架結構

###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;

###9-圖片



#總結
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即將顯示時和即將消失時需要設置的操作,這兩個方法多次調用