广

IOS开发

  • IOS开发
  • android开发
  • PHP编程
  • JavaScript
  • ASP.NET
  • ASP编程
  • JSP编程
  • Java编程
  • 易语言
  • Ruby编程
  • Perl编程
  • AJAX
  • 正则表达式
  • C语言
  • 编程开发

    详解iOS开发中使用storyboard创建导航控制器的方法

    2018-04-05 08:31:48 次阅读 稿源:互联网
    广告

    关于StoryBoard

    iOS5之后Apple提供了一种全新的方式来制作UI,那就是StoryBoard。简单理解来说,可以把StoryBoard看做是一组viewController对应的xib,以及它们之间的转换方式的集合。在StoryBoard中不仅可以看到每个ViewController的布局样式,也可以明确地知道各个ViewController之间的转换关系。相对于单个的xib,其代码需求更少,也由于集合了各个xib,使得对于界面的理解和修改的速度也得到了更大提升。减少代码量就是减少bug量,这也是程序开发中的真理之一。
     
    在Xcode5之后,StoryBoard已经成为新建项目的默认配置,这也代表了Apple对开发者的建议和未来的方向。WWDC2013的各个Sample Code中也基本都使用了StoryBoard来进行演示。可以预见到,之后Apple必定会在这方面进行继续强化,而反之纯代码或者单个xib的方式很可能不会再得到增强。
     
    如果不考虑iOS版本的支持(其实说实话现在已经很少还见到要从iOS4开始支持的app了吧),现在StoryBoard面临的最大问题就是多人协作。因为所有的UI都定义在一个文件中,因此很多开发者个人或企业的技术负责人认为StoryBoard是无法进行协作开发的,其实这更多的是一种对StoryBoard的陌生所造成的误解。虽然Apple并没有在WWDC明确提及,但是没有人规定整个项目只能有一个StoryBoard文件。一种可行的做法是将项目的不同部分分解成若干个StoryBoard,并安排开发人员对自己的部分进行负责。简单举例比如一个有4个tab功能相互独立的基于UITabBarViewController的应用,完全可以使用4个StoryBoard来分别代表4个tab,并在相互无干扰的情况下完成开发。这样一来就不会存在所谓的冲突问题了。StoryBoard的API是如此简单,现在的SDK中一共方法数量一只手就能数过来,所以具体方法在这里就不再罗嗦了。
     
    StoryBoard的另外的挑战来源于ViewController的重用和自定义的view的处理。对于前者,在正确封装接口以及良好设计的基础上,其实StoryBoard的VC重用与代码的VC重用是没有本质区别的,在StoryBoard中添加封装良好需要重用的Scene即可解决。而对于后者,因为StoryBoard中已经不允许有单个view的存在,因此很多时候我们还是需要借助于单个的xib来自定义UI。这一点可以说是由于StoryBoard的设计思路所造成的,StoryBoard更强调的是一种层次结构,是在全局的视角上来组织UI设计和迁移。而对于单个的view,更多的会注重于重用和定制,而与整个项目的流程没有太大关系。相信抓住这一要点,就能很好地了解什么时候使用xib,什么时候使用StoryBoard。
     
    关于StoryBoard最后要说的是,现在会有一些对于StoryBoard性能上的担忧。因为相对于单个xib来说,StoryBoard文件往往更大,加载速度也相应变慢。但是其实随着现在设备的更新换代,在iPhone4都难觅的今天,这点性能上的差距几乎可以忽略了。而再之后的设备,不论读取还是解析,只会越来越快。所以性能上的问题完全是没有担心的必要的。

    使用storyboard创建导航控制器以及控制器的生命周期
    一、基本过程

    新建一个项目,系统默认的主控制器继承自UIViewController,把主控制器两个文件删掉。

    在storyboard中,默认的控制器是View Controller,而我们需要的是导航控制器,那么就把系统的给删掉,拖一个导航控制器进来,导航控制器中默认的第一个子控制器是一个tableview controller,这里不需要,把它删掉,重新拖三个View Controller到界面上进行连线,简单的设置就可以了。

    按钮连线,按住ctrl,右边界面选择push。

    完成基本设置后的界面如下:

    经过这么几步简单的设置,就可以实现一个简单的多页面切换。为开发提供了极大的方便,但storyboard也不是万能的,要注意在开发中,如果在最后一个页面添加一个按钮,让它直接跳转到上一个页面会出现问题。

    提示:storyboard能做的事情,使用代码都能做,但是代码能够做的事情,storyboard不一定能够做。

    通过拖拉控件即可完成简单的界面设置。

    下面这样的连线会出现问题:(从后面的控制器跳转到前面,只能通过代码来实现)

    产生问题的原因:(当点击返回的时候,不是先把第三个控制器移除栈顶,而是先创建TWO控制器,此时栈里有四个控制器,栈顶的为TWO).

    二、控制器的生命周期

    代码简单说明:
    代码如下:

    @interface NJOneViewController ()

    @property (nonatomic, strong) NSArray *foods;
    @end

    @implementation NJOneViewController

    // 当控制器的view加载完毕就调用
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        NSLog(@"1控制器的view加载完毕");
    }

    // 控制器的view即将显示的时候调用
    - (void)viewWillAppear:(BOOL)animated
    {
        [super viewWillAppear:YES];
        NSLog(@"1控制器的view即将显示");
    }

    // 控制器的view完全显示的时候调用
    - (void)viewDidAppear:(BOOL)animated
    {
        [super viewDidAppear:animated];
        NSLog(@"1控制器的view完全显示");
    }

    // 控制器的view即将消失的时候调用
    - (void)viewWillDisappear:(BOOL)animated
    {
        [super viewWillDisappear:animated];
        NSLog(@"1控制器的view即将消失");
    }
    // 控制器的view完全消失的时候调用
    - (void)viewDidDisappear:(BOOL)animated
    {
        [super viewDidDisappear:animated];
        NSLog(@"1控制器的view完全消失");
    }

    // 控制器的view即将销毁的时候调用
    - (void)viewWillUnload
    {
        [super viewWillUnload];
    }
    // 控制器的view完全销毁的时候调用
    - (void)viewDidUnload
    {
        [super viewDidUnload];
        // 清空不需要的属性
    //    [self.foods release];
        self.foods = nil;
    }

    //- (void)setFoods:(NSArray *)foods
    //{
    //    if (_foods != foods) {
    //        [foods release];
    //        _foods = [foods retain];
    //    }
    //}

    // 接收到内存警告的时候调用
    - (void)didReceiveMemoryWarning
    {
        [super didReceiveMemoryWarning];
    }
     /**/

    @end

    打印结果如下

    三个重要的方法:
    代码如下:

    // 控制器的view即将销毁的时候调用
    - (void)viewWillUnload
    {
        [super viewWillUnload];
    }
    // 控制器的view完全销毁的时候调用
    - (void)viewDidUnload
    {
        [super viewDidUnload];
        // 清空不需要的属性
    //    [self.foods release];
        self.foods = nil;
    }

    // 接收到内存警告的时候调用
    - (void)didReceiveMemoryWarning
    {
        [super didReceiveMemoryWarning];
    }

    补充:

    两个内存警告的区别(和代理中得比较):

    代理的内存警告:当application发生一些事情的时候(接收到内存警告的时候),会先通知它的代理,之后代理会通知它的window,window会通知它的根控制器,根控制器会通知它的子控制器。内存警告是由上往下一层一层往下传的(可以通过在两个地方打印输出验证)。

    需要了解它的父类是如何处理内存警告的。

    模拟内存警告:

    内存警告的处理示意图:

    控制器的view是否可以销毁?它怎么知道是否可以销毁呢?如何判断?它是判断这个view是否是在windows上面。

    当前one控制器在栈顶,one控制器对应的view显示在window上,如果此时发生内存警告,那么one因为在window上面,所以不会被销毁。

    若此时再来一个two控制器,它创建对应的twoview显示到window上,one对应的view移开了,此时如果发生内存警告,则此时oneview已经不再在window上显示,所以会被销毁。

    特别说明:outlet代表着属性,当控制器创建的时候,属性一般也是有值的,当调用了- (void)viewDidUnload方法以后,即控制器的view完全销毁了以后,所有的属性数据会清空。一般在ios5以前,还会在这个方法里面清空里面的所有属性。

    提示:所有的控制器的这些方法其实是一个循环。

    一起学吧部分文章转载自互联网,供读者交流和学习,若有涉及作者版权等问题请及时与我们联系,以便更正、删除或按规定办理。感谢所有提供资讯的网站,欢迎各类媒体与一起学吧进行文章共享合作。

    广告
    广告
    广告