UINavigationController 和 UITabBarController视图控制器的介绍

当app中有多个控制器的时候,就需要对这些控制器进行管理,用一个控制器去管理其他多个控制器;如图所示:

1.png

IOS UIView 提供了两个特殊的控制器,UINavigationController和UITabBarController去管理其它控制器。

本文以下面的一个简单例子加以说明基本用法:

2.png

UIWindow 和 UIViewController 的基本内容

新建一个 Single View Application 工程,在iOS应用中,每个程序得main函数中都调用了UIApplicationMain函数。

1
2
3
4
5
6
#import #import "AppDelegate.h"
int main(int argc, char * argv[]) {
     @autoreleasepool {
         return  UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
     }
}

先来看看UIApplicationMain函数的原型:

1
2
3
4
5
6
UIKIT_EXTERN int UIApplicationMain(
   int argc, 
   char *argv[], 
   NSString * __nullable principalClassName, 
   NSString * __nullable delegateClassName
);

前面的argc和argv是ISO C标准的main函数的参数,直接传递给UIApplicationMain进行相关处理,principalClassName是应用程序类的名字,该类必须继承自UIApplication类,而delegateClassName是应用程序类的代理类。如果主要nib文件(在info.plist文件中指定,key是NSMainNibFile)存在,就会在nib文件对象里寻找Application对象和连接它的delegate。此函数会根据principalClassName创建UIApplication对象,然后根据delegateClassName创建一个delegate对象,并将UIApplication对象中的delegate属性设置为delegate对象,接着会建立应用的main runloop,进行事件的处理,首先调用 application:didFinishLaunchingWithOptions 。程序正常退出时才返回(如今iOS支持后台运行,系统在必要时会强行杀死不用的进程,一般这个函数不等返回进程就终止了)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 程序启动完成调用
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
     // 创建Window
     self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
     // 设置Window的背景颜色
     self.window.backgroundColor = [UIColor whiteColor];
     
     // 设置根控制器
     ViewController *vc = [[ViewController alloc] init];
     self.window.rootViewController = vc;
     // 设置并显示主窗口
     [self.window makeKeyAndVisible];
     
     return  YES;
}

UIWindow是一种特殊的UIView,通常在一个应用中只会有一个UIWindow。在ios程序启动完成后,建立的第一个视图控件就是UIWindow,接着创建一个控制器的View,最后将控制器的View添加到UIWindow上,于是控制器的View就是显示到屏幕上了。一个ios程序之所以能显示在屏幕上,完全是因为它有UIWindow,也就是说没有UIWindow就看不到任何UI界面。

控制器的创建:

扫描二维码关注公众号,回复: 929433 查看本文章
1
UIViewController *vc = [UIViewController alloc] init];

可以用isViewLoaded方法判断一个UIViewController的view是否已经被加载;控制器的view加载完毕就会调用viewDidLoad方法。

将view添加到UIWindow:

  • 直接将view添加到UIWindow中,并不理会view对应的控制器。

1
- (void)addSubView:(UIView *)view;
  • 通过设置根控制器,自动将rootViewController的view添加到UIWindow中,负责管理rootViewController的生命周期。

1
@property(nonatomic,retain) UIViewController *rootViewController;

获取 RootViewController:

第一种方法:

1
2
UIWindow *window = [UIApplication sharedApplication].keyWindow;
UIViewController *rootViewController = window.rootViewController;

第二种方法:

1
2
AppDelegate *appdelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
UIViewController *rootViewController = appdelegate.window.rootViewController;

UINavigationController 和 UITabBarController 的基本内容

UINavigationController以栈的形式保存子控制器,使用push方法能将某个控制器压入栈,使用pop方法可以移除栈顶控制器。

打开 ViewController 的方式:

1
- (void)pushViewController:(UIViewController*)viewController animated:(BOOL)animated;

三种移除 ViewController 的方式:

1
2
3
4
5
6
将栈顶的控制器移除
- (UIViewController*)popViewControllerAnimated:(BOOL)animated;
回到指定的子控制器
- (NSArray*)popToViewController:(UIViewController*)viewController animated:(BOOL)animated;
回到根控制器(栈底控制器)
- (NSArray*)popToRootViewControllerAnimated:(BOOL)animated;

初始化UINavigationController:

方法一:

1
UINavigationController *nv = [[UINavigationController alloc] init];

方法二:

1
UINavigationController *nv = [[UINavigationController alloc] initWithRootViewController:rootViewController];

UITabBarController和UINavigationController类似,UITabBarController也可以轻松地管理多个控制器,轻松完成控制器之间的切换,典型的例子就是QQ、微信等应?。但是UITabBarController其管理的视图一直存在,而UINavigationController在pop后会销毁掉,释放内存。UITabBarController通常作为整个程序的rootViewController,而且不能添加到别的container viewController中。

UITabBarController的使用步骤:

  1. 初始化UITabBarController

  2. 创建子控制器(viewcontroller)

  3. 把子控制器添加到UITabBarController

  4. 设置UIWindow的rootViewController为UITabBarController

将子控制器添加到UITabBarController:

方法一:添加单个子控制器

1
- (void)addChildViewController:(UIViewController*)childController;

方法二:添加多个子控制器

1
view.viewControllers = NSArray *childController;

UITabBarController中嵌套UINavigationController:

1.png

UINavigationController中嵌套UITabBarController:

2.png

项目实战

将UITabBarController的逻辑提取到一个独立的ViewController中。可以新建一个继承于UITabBarController的ViewController。

AppDelegate.m:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 程序启动完成调用
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
     // 创建Window
     self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
     // 设置Window的背景颜色
     self.window.backgroundColor = [UIColor whiteColor];
     
     // 设置根控制器
     ViewController *vc = [[ViewController alloc] init];
     self.window.rootViewController = vc;
     // 设置并显示主窗口
     [self.window makeKeyAndVisible];
     
     return  YES;
}

ViewController.h:

1
2
@interface ViewController : UITabBarController
@end

ViewController.m:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
- (void)viewDidLoad {
     [ super  viewDidLoad];
  
     // 创建子控制器
     HomeViewController *homeVC=[[HomeViewController alloc] init];
     [self setTabBarItem:homeVC.tabBarItem
                   title:@ "首页"
               titleSize:13.0
           titleFontName:@ "HeiTi SC"
           selectedImage:@ "i_tab_home_selected"
      selectedTitleColor:[UIColor redColor]
             normalImage:@ "i_tab_home_normal"
        normalTitleColor:[UIColor grayColor]];
     
     BlogViewController *blogVC=[[BlogViewController alloc] init];
     [self setTabBarItem:blogVC.tabBarItem
                   title:@ "博文"
               titleSize:13.0
           titleFontName:@ "HeiTi SC"
           selectedImage:@ "i_tab_blog_selected"
      selectedTitleColor:[UIColor redColor]
             normalImage:@ "i_tab_blog_normal"
        normalTitleColor:[UIColor grayColor]];
     
     UINavigationController *homeNV = [[UINavigationController alloc] initWithRootViewController:homeVC];
     UINavigationController *blogNV = [[UINavigationController alloc] initWithRootViewController:blogVC];
     // 把子控制器添加到UITabBarController
     self.viewControllers = @[homeNV, blogNV];
}

我们通常需要对tabBarItem进行设置,可以封装一个setTabBarItem方法,只需要进行简单的配置即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
- (void)setTabBarItem:(UITabBarItem *)tabbarItem
                 title:(NSString *)title
             titleSize:(CGFloat)size
         titleFontName:(NSString *)fontName
         selectedImage:(NSString *)selectedImage
    selectedTitleColor:(UIColor *)selectColor
           normalImage:(NSString *)unselectedImage
      normalTitleColor:(UIColor *)unselectColor
{
     
     //设置图片
     tabbarItem = [tabbarItem initWithTitle:title image:[[UIImage imageNamed:unselectedImage]imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] selectedImage:[[UIImage imageNamed:selectedImage]imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]];
     
     // S未选中字体颜色
     [[UITabBarItem appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName:unselectColor,NSFontAttributeName:[UIFont fontWithName:fontName size:size]} forState:UIControlStateNormal];
     
     // 选中字体颜色
     [[UITabBarItem appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName:selectColor,NSFontAttributeName:[UIFont fontWithName:fontName size:size]} forState:UIControlStateSelected];
}

然后对每个子ViewController进行自定义即可,如BlogViewController.h可以这样写:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- (void)viewDidLoad {
     [ super  viewDidLoad];
     
     UIButton *helloBtn = [[UIButton alloc] initWithFrame:CGRectMake(100, 100, SCREEN_WIDTH - 200, 50)];
     helloBtn.backgroundColor = [UIColor redColor];
     [helloBtn setTitle:@ "hello world"  forState:UIControlStateNormal];
     [helloBtn addTarget:self action:@selector(showToast) forControlEvents:UIControlEventTouchUpInside];
     [self.view addSubview:helloBtn];
}
- (void)showToast{
     // 打开新ViewController
     BlogDetailViewController *blogDetail = [[BlogDetailViewController alloc] init];
     blogDetail.hidesBottomBarWhenPushed=YES;
     [self.navigationController pushViewController:blogDetail animated:YES];
}

转载:http://www.cocoachina.com/ios/20170801/20094.html

猜你喜欢

转载自blog.csdn.net/Listron/article/details/80346814