• Storyboard


    原文: http://www.raywenderlich.com/5138/beginning-storyboards-in-ios-5-part-1

    故事板是 iOS5 中激动人心的新特性,将极大节省你编写用户界面的时间。要想明白什么是故事板,请看下图。这同时也是本教程将创建的故事板:

    你也许不知道这个程序是干什么的,但它的主要屏幕界面及每个屏幕窗口之间的关系则通过这张图一目了然了。这就是使用故事板的好处。

    如果你的 app 有大量的窗口,故事板能帮你减少许多用于从一个窗口转到另一个窗口的导航代码。与每个viewcontroller 一个单独的 nib 文件不同,你的 app 只需用一个故事板文件(其中可以包含所有的 viewcontroller 以及它们之间的关系)即可。

    与传统的 nib 文件不同,故事板文件有以下优点:

    • 通过一个故事板文件,你能对所有的窗口以及它们之间的关系一目了然。因为所有的窗口设计在一个故事板文件中,你会更容易把握每次改动带给每个窗口的变化。
    • 在故事板中可以描述各个窗口之间的转换。这种转换叫做 segue(连接)。创建 segue 只需用 ctrl+ 拖拽从一个 viewcontroller 拖到另一个 viewcontroller 即可。这将减少窗体导航的代码。
    • 哪怕在 tableview 上故事板仍然有用,例如定制 tableviewcell。你完全可以在故事板编辑器中设计自己的 tableview,这也节省了不少代码。

    当然,有一利必有一弊。故事板的使用仍然有一些限制。故事板编辑器并不会比IB 更强大,有的事情只有在 IB 中能做到而使用故事板则无法做到。此外你可能需要更大的屏幕,尤其是对于 iPad 程序。

    如果你嫉妒仇恨 IB 并且喜欢使用纯粹的代码方式创建用户界面,那么故事板并不适合于你。顺便说一句,我只想尽可能地少写代码——尤其是UI 代码!——所以故事板完全对我的胃口。

    在iOS4 和 Xcode4.2 中仍然可以用 nib 文件。IB 并不会因为有了故事板就不让你用nib 文件。如果你仍然想用 nib,你可以同时使用故事板和 nib 文件。它们并不互相矛盾。

    通过本教程,你将明白你能用故事板做些什么。程序本身很无聊,但它却能演示如何用故事板应付最常见的需求。

    开始

    打开 Xcode 创建一个Single View Application。注意填写如下选项:

    • Product Name: Ratings
    • Company Identifier: 公司前缀,用反域名规则。
    • Class Prefix: 空
    • Device Family: iPhone
    • Use Storyboard: 勾选本项
    • Use Automatic Reference Counting: 勾选本项
    • Include Unit Tests: 不要勾选本项

    在新项目中包含了两个类:AppDelegate 和ViewCotnroller。以及本教程的核心: MainStoryboard.storyboard 文件。注意,并没有 xib 文件,甚至是MainWindow.xib。

    点击 MainStoryboard.storyboard 文件,将打开故事板编辑器:

    故事板编辑器从外表上看很像是 IB。你可以从 Object Library中拖控件(右下角)到 viewcontroller 中,并修改它的布局。不同的是,故事板中不仅仅包含一个 viewcontroller,而是包含 app 中的所有viewcontroller。

    故事板有一个专门的术语“场景”,一个“场景”用于表示一个viewcontroller。你以前每个场景/viewcontroller 就要用一个单独的 nib 文件,但现在所有的东西都集中到了一个故事板中。

    对于 iPhone 应用,一次可以看一个场景,但 iPad 应用可以一次显示多个场景,例如使用splitview 的“主-细”窗口,或者用 popovercontroller 弹出内容。

    先来体验一下如何使用故事板编辑器。拖几个控件到空白的viewcontroller 中。

    左侧边栏显示的是 Document Outline(文档树):

    在 IB 中这个区域往往是用于列出 nib 文件中的组件。但在故事板编辑器中,它显示的是你所有的viewcontroller 的内容。当然,当前我们的故事板中只有一个 viewcontroller ,但接下来我们将添加更多的 viewcontroller。

    文档树有一个“缩小”的版本,即下图中的“Dock”所示:

    在 Dock 上,显示了场景的顶级对象。对于每个场景,起码有一个First Responder 和一个 viewcontroller,此外也可能还会有其他的顶级对象。后边会具体说明。Dock 对于创建连接尤其有用。如果你想将什么东西连接到viewcontroller,你可以很方便地将它们拖到 Dock 上。

    注意:你可能不是很常用到FirstResponder。这是一个代理对象,指向在某个时刻中拥有first responder 状态的对象。在IB 中同样有这个对象,但你可能从始至终都没用过它。举个例子,你可以将按钮的 TouchUpInside 事件连接到First Responder 的 cut: 方法。如果某个时刻有一个 textfield 拥有了焦点,这个时候当你按下按钮,则这个 textfield (即当前时刻的first responder)将调用 cut: 方法,将它的文本剪贴到剪贴板中。

    运行程序。

    如果你以前创建过基于 nib 的 app(译者注:Xcode 3.x),你可能知道MainWindow.xib 文件。这个 nib 文件中包含了一个顶层的连接到 App Delegate 的 UIWindow 对象,以及一个或多个viewcontroller。但是,当你使用故事板的时候,所有的 UI 都放到了一个故事板中, MainWindow.xib 不再使用。

    那么,在没有 MainWindow.xib 文件的情况下,故事板是怎样被加载到app 中的呢?

    打开 AppDelegate.h,你将看到这几句:

    #import <UIKit/UIKit.h>  

    @interface AppDelegate : UIResponder <UIApplicationDelegate>  

    @property (strong, nonatomic) UIWindow *window;  

    @end

    当使用故事板的时候,应用程序委托必须从 UIResponder 开始继承(原先则直接从NSObject 继承),同时还有一个 UIWindow 属性(不同的是,它不是一个 IBOutlet)。

    在 AppDelegate.m 中,它实际上什么也没做,所有的方法都是空的。甚至application:didFinishLaunchingWithOptions: 也只是简单地返回 Yes。如果是过去,要么要在这里加入主viewcontroller 的 view 到 window,要么设置 window 的 rootViewController 属性。但现在什么都没有。

    秘密都位于 Info.plist 文件。打开Ratings-Info.plist(在 Supporting Files 文件组),

    在 nib-based 的项目中,Info.plist 文件中有一个名为 NSMainNibFile 或者 Main nib file base name 的键,它会导致UIApplication 去加载 MainWindow.xib 并将之连接到 app 中。现在,Info.plist 中不再有这个设置。

    与之对应的是,故事板应用程序使用 UIMainStoryboardFile或者“Main storyboard file base name”键。它要求应用程序在启动时需要加载的故事板文件名。当这个键缺失时,UIApplication将默认加载 MainStoryboard.storyboard 文件并自动将故事板中第一个 viewcontroller 初始化并放到一个新创建的UIWindow 对象中。这一切不再需要手工编写代码。

    你可以查看 Target 的 Summary 窗口:

    新增的 iPhone/iPodDeployment Info 小节下面,可以让你选择是从故事板文件启动还是从nib文件启动。

    为了更清楚一点,可以打开 main.m 查看:

    #import <UIKit/UIKit.h>  

    #import "AppDelegate.h"  

    int main(int argc, char *argv[]) {

            @autoreleasepool {

                   return UIApplicationMain(argc, argv, nil,             NSStringFromClass([AppDelegate class]));

         }

    }

    原先的 UIApplicationMain() 的最后一个参数为nil ,但现在是 NSStringFromClass([AppDelegate class])。

    与使用 MainWindow.xib 的时候不同,故事板中不会包含应用程序委托。由于无法从nib 中加载应用程序委托,也无法从故事板文件中加载应用程序委托,我们必须告诉 UIApplicationMain 应用程序委托类的名称,否则它根本无法找到应用程序委托类。

    使用TabBar

    Ratings 程序有一个 Tabbar,包含了两个viewcontroller。使用故事板创建 Tabbar 是小事一碟。

    切换到MainStoryboard.storyboard ,拖一个 TabBarController 到画布中。你可能得将Xcode 窗口最大化,因为TabBarController跟两个 viewcontroller 联系在一起,你可能需要更多的空间才能灵活操作。

    新的 TabBarController 已经事先配置了两个ViewController,每个 Tab 按钮一个。UITabBarController 是一种 ViewController 的容器,它包含了多个viewcontroller。其它类似的容器还有 NavigationController 和 SplitViewController(后面都会介绍)。iOS5 有个更酷的特性是你可以写自己的 ViewController 容器——在本书后续教程中介绍。

    TabBarController和所包含的ViewController的包容关系用一个箭头(中间有一个小圆图标)表示。

    注意:如果要把TabBarController与其包含的ViewController一起移动,用Cmd+左键将它们全部选中然后移动(选中的场景会有一个浅蓝色的方框框住)。

    在第一个 ViewController 中放入一个 Label 然后输入文本“FirstTab”。在第2个ViewController 中放入一个 Label 并输入文本“Second Tab”。这样我们就能在切换 Tab 时区分两个ViewController。

    注意:你不能在编辑器的缩放模式下向场景拖放东西,必须首先恢复到普通模式下。

    选中 TabBarController 并打开属性面板。勾选“ IsInitial View Controller”选项。

    在画布中,原来指向最初的 ViewController 的箭头,现在指向了TabBarController。

    也就是说,程序运行时,UIAppliation 会将 TabBarController作为应用程序的第一个ViewController。

    故事板总是以一个 ViewController 作为“initialview controller”,即故事板的入口。

    运行程序。现在的程序,可以通过 TabBarController 在两个ViewController 中切换。

    Xcode 其实有一个专门用于 Tabbar 应用程序的模板(叫做 Tabbed Application 模板),当然 我们也可以使用这个模板。但在某些时候我们必须通过手动创建TabbarController ,这样就必须知道在不使用模板时应该如何去做。

    现在你可以删除项目模板原来创建的那个 viewcontroller,我们不再需要它。这样故事板中只会有一个TabbarController 和它的两个 viewcontroller。

    以这种方式,你可以创建超过 5 个的 ViewController 给TabBarController,它将自动在 Tabbar 上显示 More... 按钮。

    添加Table View Controller

    被连接到 TabBarController 的两个场景只是一般的UIViewController。现在我们要其中的第一个替换为 UITableViewController。

    选中第一个 ViewController,删除它。拖一个TablViewController 到画布中.

    选中 TablViewController,选择菜单“EditorEmbedInNavigation ”。

    这将导致增加一个 ViewController 到画布中:

    当然你也可以直接从 Object Library 中拖一个 NavigationController,但 Embed In 命令更简单一些。

    由于 NavigationController 也是一种ViewController 容器,它和 TableViewController 之间也有一个箭头表示二者关系。在文档树中这些关系显示如图中所示:

    注意 TableViewController 上被加入了一个navigationBar。这是故事板编辑器自动放入的,因为这个场景现在将在 NavigationController 的 frame 内显示。当然,这并不是真正的UINavigationBar对象,而只是一个模拟的“假”的导航条。

    打开 TableViewcontroller 的属性面板,我们可以看到顶部有一个Simulated metrics 小节.

    故事板默认使用“Inferred”(依靠推断)设置,意思是该场景如果在NavigationController 中显示则会显示导航条,如果在 TabBarController 中显示则会显示 TabBar,等等。如果你需要的话也可以改变这些设置,但请明白,这些设置仅仅是帮助你设计你的屏幕,Simulated Metrics 并不会用于运行时,它们仅仅是帮助你进行可视化设计的。

    现在将新场景连接到TabBarController 。ctrl+左键,从TabBarController 拖一条线到 NavigationController.

    拖完后将显示弹出菜单,请选择Relationship-viewControllers。这将在这两者间创建新的关系:

    TabBarController 现在有两个关系,一个 Tab 一个。NavigationController自己有一个关系,连接的是 TableViewController。此外还有另外一种箭头,“segue”,我们在后面讲。

    创建新连接时,新的 Tab 也同时被加到 TabBarController上,名字叫做 “Item”。我想将新的场景放在第一个Tab 上,可以用拖拽 Tab 的方式改变它们的顺序.

    运行程序,现在第一个 Tab 已经变成了 NavigationController。

    在我们将实际的功能加入 app 之前,让我们整理一下我们的故事板。我想将第一个tab 命名为 Players,第2个 tab 命名为 Gestures。你不需要去改变 TabBarController,而是要改变与 tab 对应的ViewController。

    当你将一个 ViewController 连接到TabBarController 时,会在 ViewController 上创建一个 TabBarItem 对象。通过 TabBarItem 对象,你可以设置Tab 的 Title 和图片。

    选择 NavigationController 上的 TabBarItem对象,在属性面板,设置它的 Title 为 Players.

    将第二个 ViewController 的 TabBarItem 重命名为Gestures。

    我们还可以在 Tab 上放入图片。在本教程源代码中有一个文件夹Images。将该文件夹添加到项目中去。在 TabBarItem “Guestures”的属性面板,将 Players.png 设为它的image。将 TabBarItem “Players”的 image 设置为 Players.png.

    与之相仿,在 NavigationController 所包含的ViewController 上,有一个 NavigationItem 对象,可用于设置导航栏。选择 TableViewController 上的NavigationItem,在属性面板中将 title 修改为 Players。

    当然,你也可以通过简单地双击 NavigationBar 来修改title(注意:你应该双击 TableViewController 上的“假”导航条,而不是双击 NavigationController 上的真导航条。

    运行程序,不需要你编写一行代码,我们定制的 Tab 栏就显示出来了。

    1
  • 相关阅读:
    箭头函数和普通函数的区别是什么?
    前端如何优化网站性能?
    instanceof原理
    call、apply区别
    函数的节流和防抖
    关于this的指向性问题
    undefined 和null的区别?
    浅谈堆和栈的理解?
    关于vue中watch和computed
    简单说一下什么是回流和重绘
  • 原文地址:https://www.cnblogs.com/fantasy3588/p/4969077.html
Copyright © 2020-2023  润新知