美文网首页
UINavigationController

UINavigationController

作者: ilaoke | 来源:发表于2015-08-01 19:48 被阅读615次

    UINavigationController

    当界面交互是:列表-->明细-->更具体的明细,这种情况就需要用UINavigationController

    UINavigationController维护a stack of those screens,每一个screen都是UIViewController的view,stack是一个view controller数组。

    当创建UINavigationController实例时,为其指定一个UIViewController,这个view controller就是navigation controller's root view controller,其总在stack的最下面。

    和UITabBarController一样,UINavigationController也有一个viewControllers数组,root view controller是这个数组的第一个对象,当更多的view controller push到stack时,他们被添加到这个数组中,数组的最后一个对象总是在stack的顶部,UINavigationController's topViewController属性指向栈顶的view controller。

    UINavigationControllerUIViewController的子类,所以他也有一个view属性,其view有两个subview:UINavigationBar和topViewController

    将navigation controller设置为窗口的rootViewController

    #import "BKAppDelegate.h"
    #import "BKItemsViewController.h"
    
    @implementation BKAppDelegate
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
        // Override point for customization after application launch.
       
        BKItemsViewController *itemsViewController = [[BKItemsViewController alloc] init];
        // Create an instance of UINavigationController
        UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:itemsViewController];
        self.window.rootViewController = navController;
        
        
        self.window.backgroundColor = [UIColor whiteColor];
        [self.window makeKeyAndVisible];
        return YES;
    }
    
    @end
    

    创建BKDetailViewController

    创建BKDetailViewController类,继承UIViewController类,同时创建XIB文件。


    打开assistant editor

    在project navigator,Option-click BKDetailViewController.m文件,打开assistant editor

    simulated metrics

    选择root view,然后打开attributes inspector,在Simulated Metrics section为top bar选择Translucent Navigation Bar,可以模拟navigation bar的显示


    将XIB中的视图outlet到 view controller

    Control-drag UITextField到view controller的class extension中。


    将view controller放入navigation controller's stack

    navigation controller's stack中的view controller,都可以通过navigationController方法来获得navigation controller.

    root view controller创建下一个view controller,并把他放入到navigation controller stack中,然这个view controller创建下一个需要入栈的view controller,以此类推。

    // 选中一行
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
        BKDetailViewController *detailViewController = [[BKDetailViewController alloc] init];
        [self.navigationController pushViewController:detailViewController animated:YES];
    }
    

    在view controllers之间传递数据

    Having all of the data in the root view controller and passing subsets of that data to the next UIViewController is a clean and efficient way of performing this task.

    为了让BKDetailViewController显示BKItem的各属性值,需要将BKItem传递给detail view controller.

    在BKDetailViewController头文件中声明BKItem属性:

    #import <UIKit/UIKit.h>
    
    @class BKItem;
    
    @interface BKDetailViewController : UIViewController
    
    @property (nonatomic,strong) BKItem *item;
    
    @end
    
    

    当BKDetailViewController‘s view显示到屏幕上之前,将BKItem的值设置到其view上,所以在viewWillAppear:中设置

    #import "BKDetailViewController.h"
    #import "BKItem.h"
    
    @interface BKDetailViewController ()
    @property (weak, nonatomic) IBOutlet UITextField *nameField;
    @property (weak, nonatomic) IBOutlet UITextField *serialField;
    @property (weak, nonatomic) IBOutlet UITextField *valueField;
    @property (weak, nonatomic) IBOutlet UILabel *dateLabel;
    
    @end
    
    @implementation BKDetailViewController
    
    - (void)viewWillAppear:(BOOL)animated{
        [super viewWillAppear:animated];
        
        BKItem *item = self.item;
        
        self.nameField.text = item.itemName;
        self.serialField.text = item.serialNumber;
        self.valueField.text = [NSString stringWithFormat:@"%d", item.valueInDollars];
        
        static NSDateFormatter *dateFormatter = nil;
        if(!dateFormatter){
            dateFormatter = [[NSDateFormatter alloc] init];
            dateFormatter.dateStyle = NSDateFormatterMediumStyle;
            dateFormatter.timeStyle = NSDateFormatterNoStyle;
        }
        self.dateLabel.text = [dateFormatter stringFromDate:item.dateCreated];
    }
    
    @end
    

    更新BKItemsViewController.m,为BKDetailViewController传值:

    // 选中一行
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
        BKDetailViewController *detailViewController = [[BKDetailViewController alloc] init];
        
        NSArray *items = [[BKItemStore sharedStore] allItems];
        BKItem *selectedItem = items[indexPath.row];
        
        detailViewController.item = selectedItem;
            
        [self.navigationController pushViewController:detailViewController animated:YES];
    }
    

    Appearing and disappearing views

    当navigation controller切换视图时,会分别发送viewWillDisappear:viewWillAppear:到将消失和将显示的view controller

    When the message endEditing: is sent to a view, if it or any of its subviews is currently the first responder, it will resign its first responder status, and the keyboard will be dismissed.

    当BKDetailViewController的视图将要消失时,更新BKItem:

    // 在视图要消失前,更新BKItem
    - (void)viewWillDisappear:(BOOL)animated{
        
        [super viewWillDisappear:animated];
        [self.view endEditing:YES];
        
        BKItem *item = self.item;
        item.itemName = self.nameField.text;
        item.serialNumber = self.serialField.text;
        item.valueInDollars = [self.valueField.text intValue];
    }
    

    在BKItemsViewController的视图将要显示时,刷新table view:

    - (void)viewWillAppear:(BOOL)animated{
        [super viewWillAppear:animated];
        
        [self.tableView reloadData];
    }
    

    UINavigationBar

    每一个UIViewController有一个navigationItem属性,其类型是UINavigationItem,不像UINavigationBar,UINavigationItem不是UIView的子类,所以他不能出来显示在屏幕上。

    当一个view controller在navigation controller的栈顶时,UINavigationBar用这个view controller的navigationItem的值来配置自己。

    简单navigation item

    默认,navigation item是空,最简单的navigation item,可以只配置他的title属性。

    当一个view controller在navigation controller的栈顶时,并且其navigationItem有一个有效的title属性,navigation bar就会显示这个title。

    修改BKItemsViewController.m,在初始化时设置navigationItem's title:

    - (instancetype)init{
        self = [super initWithStyle:UITableViewStylePlain];
        
        if(self){
            // 设置其本身的navigationItem
            UINavigationItem *navItem = self.navigationItem;
            navItem.title = @"Homepwner";
        }
           
        return self;
    }
    

    当为BKDetailViewController设置BKItem时(set方法),设置其navigationItem title为BKItem's name。

    - (void)setItem:(BKItem *)item{
        _item = item;
        self.navigationItem.title = _item.itemName;
    }
    

    复杂navigation item

    navigation item不光可以只定义title属性,还可以很复杂。如下图所示,每个UINavigationItem有三个可自定义区:leftBarButtonItem,rightBarButtonItem,titleView。
    前两个是UIBarButtonItem实例,这个类型的实例只能用来配置UINavigationBar或UIToolbar中的button的显示内容。

    和UINavigationItem一样,UIBarButtonItem也不是UIView的子类,所以不能显示在屏幕上。

    第三个titleView,可以是一个基本的title字符串,也可以是任意的UIView子类,只能任选一种。

    下面将BKItemsViewController的headerView(自定义的view)替换成UINavigationBar。

    navigation bar 的button,和UIControl 的target-action机制一样,当被点击,发送action消息到target。
    在XIB中设置target-action pair,Control-drag button组件到target,并选择IBAction list中的一个。
    也可以通过代码的方式,创建target-action pair,传递target和action到button.

    在BKItemsViewController.m文件,创建UIBarButtonItem实例,并为其传递target和action。

    - (instancetype)init{
        self = [super initWithStyle:UITableViewStylePlain];
        
        if(self){
            // 设置其本身的navigationItem
            UINavigationItem *navItem = self.navigationItem;
            navItem.title = @"Homepwner";
            
            // 创建一个bar button item,并设置target action
            UIBarButtonItem *bbi = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addNewItem:)];
            // 将bar button item设置给navigation item
            navItem.rightBarButtonItem = bbi;
            
            navItem.leftBarButtonItem = self.editButtonItem;
        }
           
        return self;
    }
    

    action传递的是一个SEL类型,这个类型指定一个方法(就是selector),@selector()不关心返回类型,参数类型或参数名称。

    UIViewController有一个editButtonItem属性,当调用这个属性,view controller创建一个title为Edit的UIBarButtonItem,并且已经设置好了target-action,当被点击时,发送setEditing:animated:消息到UIViewController。

    现在可以把自定义的headerView删除了。


    本文是对《iOS Programming The Big Nerd Ranch Guide 4th Edition》第十章的总结。

    相关文章

      网友评论

          本文标题:UINavigationController

          本文链接:https://www.haomeiwen.com/subject/rpkvqttx.html