ios 視圖控制器和導航模式

控制器切換方式:
model 是所有控制器擁有的權益,只要是控制器都可以modal出其他控制器
push 是導航控制器及其子控制器的專權,只有它們才能調用push方法
Present Modally 模態類型的過渡
View Controllers 標簽導航

一、模態視圖

  • 目的 模態視圖主要是為了完成次要任務
  • 特點 以模態窗口的形式管理視圖,當前視圖關閉前其他視圖上的內容無法操作。
  • 顯示方式 默認從屏幕下方滑出
  • 模態視圖控制器 并非專門的類,可以是其他控制器的子類,負責主要視圖的控制器為主控制器,與模態控制器為父子關系。
  • 相關方法 在ViewController類中

-presentViewController:animated:completion //呈現模態視圖
-dismissViewControllerAnimated:complation //關閉模態視圖

登錄.png
注冊.png
#import "ViewController.h"
#import "RegisterViewController.h"

@interface ViewController ()
@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    CGRect screen = [[UIScreen mainScreen] bounds];
    self.navigationItem.title = @"登錄";
    
    /// 1.添加用戶ID:標簽
    UILabel* labelId = [[UILabel alloc] initWithFrame:CGRectMake(59,115, 80, 21)];
    labelId.text = @"用戶ID:";
    [self.view addSubview:labelId];
    
    /// 2.添加用戶ID TextField
    UITextField* textFieldId = [[UITextField alloc] initWithFrame:CGRectMake(141, 106, 200, 30)];
    textFieldId.borderStyle = UITextBorderStyleRoundedRect;
    [self.view addSubview:textFieldId];
    
    /// 3.添加密碼:標簽
    UILabel* labelPwd = [[UILabel alloc] initWithFrame:CGRectMake(76, 178, 80, 21)];
    labelPwd.text = @"密碼:";
    [self.view addSubview:labelPwd];
    
    /// 4.添加密碼 TextField
    UITextField* textFieldPwd = [[UITextField alloc] initWithFrame:CGRectMake(141, 169, 200, 30)];
    textFieldPwd.borderStyle = UITextBorderStyleRoundedRect;
    [self.view addSubview:textFieldPwd];
    
    /// 5.添加 登錄按鈕
    UIButton* buttonLogin = [UIButton buttonWithType:UIButtonTypeSystem];
    buttonLogin.frame = CGRectMake((screen.size.width - 30)/2, 231, 50, 30);
    [buttonLogin setTitle:@"登錄" forState:UIControlStateNormal];
    [self.view addSubview:buttonLogin];
    
    /// 6.添加 注冊按鈕
    UIButton* buttonReg = [UIButton buttonWithType:UIButtonTypeSystem];
    buttonReg.frame = CGRectMake((screen.size.width - 30)/2, 294, 50, 30);
    [buttonReg setTitle:@"注冊" forState:UIControlStateNormal];
    [buttonReg addTarget:self action:@selector(onClick:) forControlEvents:UIControlEventTouchUpInside];
    
    [self.view addSubview:buttonReg];
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(registerCompletion:) name:@"RegisterCompletionNotification" object:nil];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)onClick:(id)sender {
    RegisterViewController* registerViewController = [[RegisterViewController alloc] init];
    UINavigationController* navigationController = [[UINavigationController alloc] initWithRootViewController:registerViewController];
   
    [self presentViewController:navigationController animated:TRUE completion:nil];
}
-(void)registerCompletion:(NSNotification*)notification {  
    NSDictionary *theData = [notification userInfo];
    NSString *username = theData[@"username"];
    NSLog(@"username = %@",username);
}

@end
#import "RegisterViewController.h"

@interface RegisterViewController ()
@property (strong, nonatomic) UITextField *txtUsername;
@end

@implementation RegisterViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.navigationItem.title = @"注冊";
    
    UIBarButtonItem *saveButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:
                                       UIBarButtonSystemItemSave target:self action:@selector(save:)];
    
    UIBarButtonItem *cancelButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:
                                         UIBarButtonSystemItemCancel target:self action:@selector(cancel:)];
    
    self.navigationItem.rightBarButtonItem = saveButtonItem;
    self.navigationItem.leftBarButtonItem = cancelButtonItem;
      
    /// 1.添加用戶ID:標簽
    UILabel* labelId = [[UILabel alloc] initWithFrame:CGRectMake(35, 187, 85, 21)];
    labelId.text = @"用戶ID:";
    [self.view addSubview:labelId];
    
    /// 2.添加Username TextField
    self.txtUsername = [[UITextField alloc] initWithFrame:CGRectMake(145, 178, 131, 30)];
    self.txtUsername.borderStyle = UITextBorderStyleRoundedRect;
    [self.view addSubview:self.txtUsername];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)save:(id)sender {  
    [self dismissViewControllerAnimated:TRUE completion:^{    
        NSLog(@"點擊Save按鈕,關閉模態視圖");   
        NSDictionary *dataDict = @{@"username" : self.txtUsername.text};    
        [[NSNotificationCenter defaultCenter] postNotificationName:@"RegisterCompletionNotification" object:nil userInfo:dataDict];
    }];   
}
- (void)cancel:(id)sender { 
    [self dismissViewControllerAnimated:TRUE completion:^{
        NSLog(@"點擊Cancel按鈕,關閉模態視圖");
    }];    
}

@end

PS:Interface Builder實現時,過渡方式選擇Present Modally 模態類型的過渡,同時需要操作的控制器需要嵌入到一個導航控制器,故事版中選擇ViewController ->Editor ->Embed ->Navigation Controller 。

二、平鋪導航

一般用于簡單的扁平化信息(信息之間沒有從屬的層次關系)瀏覽,

正在更新。。。。

三、標簽導航 (UITabBarController)

  • 特點 以平行的方式管理視圖,各個視圖之間往往關系并不大,每個加入到UITabBarController的視圖都會進行初始化即使當前不顯示在界面上,相對比較占用內存。
  • 概述 UITabBarController是Apple專門為了利用頁簽切換視圖而設計的,在這個視圖控制器中有一個UITabBar控件,用戶通過點擊tabBar進行視圖切換。我們知道在UIViewController內部有一個視圖,一旦創建了UIViewController之后默認就會顯示這個視圖,但是UITabBarController本身并不會顯示任何視圖,如果要顯示視圖則必須設置其viewControllers屬性(它默認顯示viewControllers[0])。這個屬性是一個數組,它維護了所有UITabBarController的子視圖。為了盡可能減少視圖之間的耦合,所有的UITabBarController的子視圖的相關標題、圖標等信息均由子視圖自己控制,UITabBarController僅僅作為一個容器存在。
  • 總結
    1> UITabBarController會一次性初始化所有子控制器,但是默認只加載第一個控制器視圖,其他視圖控制器只初始化默認不會加載,為了能夠將其他子控制器也正常顯示在Tab bar中我們訪問了每個子視圖控制器的視圖以便調用其視圖加載方法(viewDidLoad);當然,既然會調用子視圖的初始化方法,當然也可以將視圖控制器的tabBarItem屬性設置放到init方法中設置,如此則不用再遍歷其視圖屬性了。
    2> 每個視圖控制器都有一個tabBarController屬性,通過它可以訪問所在的UITabBarController,而且對于UITabBarController的直接子視圖其tabBarController等于parentViewController。
    3> 每個視圖控制器都有一個tabBarItem屬性,通過它控制視圖在UITabBarController的tabBar中的顯示。
    4> tabBarItem的image屬性必須是png格式(建議大小32*32)并且打開alpha通道否則無法正常顯示。

四、樹形結構導航

  • 目的 導航視圖(UINavigationController)和表視圖(UITableView)結合使用,用于構建有從屬關系的導航。
  • 特點
    a. UINavigationController 以棧的方式管理視圖,各個視圖的切換就是壓棧和出棧操作,出棧后的視圖會立即銷毀。UINavigationController是一個導航控制器,它用來組織有層次關系的視圖,在UINavigationController中子控制器以棧的形式存儲,只有在棧頂的控制器能夠顯示在界面中,一旦一個子控制器出棧則會被銷毀。UINavigationController默認也不會顯示任何視圖(這個控制器自身的UIView不會顯示),它必須有一個根控制器rootViewController,而且這個根控制器不會像其他子控制器一樣被銷毀。
  • 總結

1> UINavigationController默認顯示一個根控制器,這個根視圖必須指定(前面我們說過UINavigationController和UITabBarController類似僅僅作為導航容器,本身并不會顯示視圖),通過根控制器導航到其他下一級子視圖。
2> 在子視圖中可以通過navigationController訪問導航控制器,同時可以通過navigationController的childViewControllers獲得當前棧中所有的子視圖(注意每一個出棧的子視圖都會被銷毀)。
3> UINavigationController導航是通過上方導航欄進行的(類似的UITabBarController是通過下方UITabBar進行導航),每個放到UINavigationController棧中的子視圖都會顯示一個導航欄,可以通過子控制器(包括根控制器)的navigationItem訪問這個導航欄,修改其左右兩邊的按鈕內容。
4> 默認情況下除了根控制器之外的其他子控制器左側都會在導航欄左側顯示返回按鈕,點擊可以返回上一級視圖,同時按鈕標題默認為上一級視圖的標題,可以通過backBarButtonItem修改。下一級子視圖左側返回按鈕上的標題的顯示優先級為: 導航欄返回按鈕backBarButtonItem的標題(注意不能直接給backBarButtonItem的標題賦值,只能重新給backBarButtonItem賦值)、導航欄navigationItem的標題,視圖控制器標題。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容