UIStoryboard 故事板

前言

  • Objective-C

    1
    NS_CLASS_AVAILABLE_IOS(5_0) @interface UIStoryboard : NSObject
  • Swift

    1
    @available(iOS 5.0, *) public class UIStoryboard : NSObject
  • StoryBoard 是苹果在 iOS5 中引入的新技术方案,目的是给纷繁复杂的 nib、xib 们一个温暖的家,让他们之间的关系更直观地展示出来,并提供了一种新的页面间跳转方式 Segue。StoryBoard 的本质是一个 XML 文件,描述了若干窗体、组件、Auto Layout 约束等关键信息。Storyboard 不止是包含一个视图控件,而是所有的视图控件以及他们之间的关系。

  • Storyboard 对一个视图的官方术语是一个场景,但是一个场景其实就是一个 ViewController,用来描述软件界面,在 iPhone 中一次只能够展示一个场景,而在 iPad 中一次可以展示多个场景。一个项目中可以有不止一个 StoryBoard 文件,它们之间可以互相调用。

  • 使用 StoryBoard 的 iOS 项目均以初始化 StoryBoard 文件作为整个程序的初始化入口,UIViewController 类是由于被 StoryBoard 绑定而初始化,从而开始运行的。

1、StoryBoard

1.1 StoryBoard 视图界面

Storyboard1

  • 加载 StoryBoard 时会首先创建和显示箭头所指的控制器界面。

1.2 Storyboard 到代码的转换

  • 代码编译时编译器会自动将 Storyboard 转换为相应的代码。

    Storyboard8

  • 上图设置自动转换为:

    • Objective-C

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      // 创建一个自定义的按钮
      UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]

      // 默认状态的文字
      [btn setTitle:@"点我啊" forState:UIControlStateNormal];

      // 默认状态的文字颜色
      [btn setTitleColor:[UIColor redColor] forState:UIControlStateNormal];

      // 默认状态的背景
      [btn setBackgroundImage:[UIImage imageNamed:@"btn_01"] forState:UIControlStateNormal];

2、StoryBoard 界面设置

2.1 启动 StoryBoard 设置

  • 修改 TARGETS => General => Development Info => Main Interface 的值。或者修改 Info.plist 文件中键 Main storyboard file base name 对应的值可以修改程序启动时加载的 StoryBoard。

    Storyboard6


    Storyboard7

  • 这个设置表明:程序启动时会加载 Main.storyboard

2.2 View Controller 设置

2.2.1 Identity 设置面板

Storyboard2

Custom Class .
– Class StoryBoard 绑定的视图控制器
– Module
Identity
– StoryBoard ID StoryBoard 的 ID
– Restoration ID
— Use StoryBoard ID 设置是否使用 StoryBoard ID

2.2.2 Attributes 设置面板

Storyboard3

Simulated Metrics .
– Size 屏幕尺寸
— Inferred 自动推断
— Freeform 自定义
— Page Sheet
— Form Sheet
— Master 主控制页
— Detail 详情页
– Orientation 屏幕方向
— Portrait 竖屏
— Landscape 横屏
– Status Bar 状态栏
– Top Bar 顶部控制条
– Bottom Bar 底部控制条
View Controller
– Title
— Is Initial View Controller 设为初始场景,场景前面会显示灰色的小箭头,程序启动后会将这个场景作为应用程序的主屏幕
– Layout
— Adjust Scroll View Insets
— Hide Bottom Bar on Push 推出新的视图时隐藏底部控制条
— Resize View From Nib
— Use Full Screen (Deprecated)
– Extend Edges
— Under Top Bars
— Under Bottom Bars
— Under Opaque Bars
– Transition Style 设置页面出现效果
— Cover Vertical 向上推出
— Flip Horizontal 水平翻转
— Cross Dissoive 出现
— Partial Curl 向上翻页
– Presentation
— Full Screen
— Current Context
— Page Sheet
— Form Sheet
— Over Full Screen
— Over Current Context
—- Defines Context
—- Provides Context
– Content Size
— Use Preferred Explicit Size

2.3 View 设置

2.3.1 Attributes 设置面板

Storyboard4

View .
– Mode
– Tag
– Interaction
— User Interaction Enabled 用户交互属性
— Multiple Touch 多点触控
– Alpha
– Background 背景颜色
– Tint 前景颜色
– Drawing
— Opaque
— Hidden 隐藏视图
— Clears Graphics Context
— Clip Subviews 子视图范围不允许超过父视图
— Autoresize Subviews 允许子视图随父视图缩放
– Stretching

3、StoryBoard 关联

3.1 添加控件代码关联

  • 打开 Assistant Editor 同时显示界面设计与代码,按住 Ctrl 键同时拖动控件到代码里,在弹出的上下文菜单中设置需要关联的类型,即可在代码里自动生成代码,这里主要有两种关联类型,一种是 Outlet 连接,就是在代码里创建界面元素的成员变量引用,另一种是 Action 事件,把界面元素的响应事件方法添加到代码里来。如果已经创建了代码,也可以把控件直接拖放到对应代码上,这时候就不是插入而是直接建立连接了。

  • 1) IBAction:
    从返回值角度上看,作用相当于 void,只有返回值声明为 IBAction 的方法,才能跟 storyboard 中的控件进行连线。

  • 2) IBOutlet:
    只有声明为 IBOutlet 的属性,才能跟 storyboard 中的控件进行连线。

  • 3) 连线容易出现的问题:
    如果遇到这种错误,90% 的可能都是因为连线有问题,比如一些线已经 “过期”。

    • 1> 连接的方法代码被删掉,但是连线没有去掉:

      1
      2
          unrecognized selector sent to instance 0x7f9bf9610910libc++abi.dylib: terminating with 
      uncaught exception of type NSException
    • 2> 连接的属性代码被删掉,但是连线没有去掉:

      1
      2
          'NSUnknownKeyException', reason: '[<ViewController 0x7fdf7048b200> setValue:forUndefinedKey:]: 
      this class is not key value coding-compliant for the key
  • Objective-C

    1
    2
    3
    4
    5
    6
    7
    // Outlet 连接
    @property (weak, nonatomic) IBOutlet UILabel *myLabel;

    // Action 事件
    - (IBAction)buttonClick:(UIButton *)sender {

    }
  • Swift

    1
    2
    3
    4
    5
    6
    7
    // Outlet 连接
    @IBOutlet weak var myLabel: UILabel!

    // Action 事件
    @IBAction func buttonClick(sender: UIButton) {

    }

3.2 添加 segue 关联

  • 右键(或 control + 鼠标左键)拖动控件到目标场景,在弹出的上下文菜单中选择 show 等。如果是两个 Controller 之间建立包含关联,则上下文之间会有 Relationship Segue 的选项,选择 view controller 即可。

  • segue 界面关联类型:

    Storyboard5

Relationship Segue 包含关联
show 导航推出,推出页自带返回按钮
show detail 详情推出
present modally 视图控制器之间跳转
popover presentation 视图控制器之间跳转返回
custom 自定义方式跳转
  • Objective-C

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // 系统自带场景跳转相关方法,可以不写该方法
    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

    /*
    segue:场景里跳转的线
    sender:触发跳转的对象
    */

    // 获取目标视图控制器
    UIViewController *viewController = segue.destinationViewController;
    viewController.view.backgroundColor = [UIColor orangeColor];
    }
  • Swift

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // 系统自带场景跳转相关方法,可以不写该方法
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

    /*
    segue:场景里跳转的线
    sender:触发跳转的对象
    */

    // 获取目标视图控制器
    let viewController = segue.destinationViewController
    viewController.view.backgroundColor = UIColor.purpleColor()
    }

4、StoryBoard 场景跳转

  • 1)创建 按钮 与 Controller 间 segue 关联,无需添加代码,直接点击按钮即可实现页面跳转。

  • 2)创建 Controller 与 Controller 间 segue 关联,并设置 segue 的 Identifier 值,在按钮点击响应事件中添加页面跳转代码。

    • Objective-C

      1
      2
      // 根据 segue Identifier 跳转界面
      [self performSegueWithIdentifier:@"segueIdentifier" sender:self];
    • Swift

      1
      2
      // 根据 segue Identifier 跳转界面
      self.performSegueWithIdentifier("segueIdentifier", sender: self)
  • 3)设置要跳转到的 Controller 的 StoryBoard ID,在按钮点击响应事件中添加页面跳转代码。

    • Name:StoryBoard 文件名称,Identifier:ViewController 中设置的 StoryBoard ID 名称

    • Objective-C

      1
      2
      3
      4
      5
      UIViewController *secondViewController = [[UIStoryboard storyboardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:@"storyboardID"];

      UIViewController *secondViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"storyboardID"];

      [self presentViewController:secondViewController animated:YES completion:nil];
    • Swift

      1
      2
      3
      4
      5
      let secondViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("storyboardID") 

      let secondViewController = self.storyboard!.instantiateViewControllerWithIdentifier("storyboardID")

      self.presentViewController(secondViewController, animated: true, completion: nil)
  • 4)不同 StoryBoard 文件中,设置要跳转到的 Controller 的 Is Initial View Controller 或者 StoryBoard ID,在按钮点击响应事件中添加页面跳转代码。

    • 若 StoryBoard 中设置了 Is Initial View Controller 可以直接使用 instantiateInitialViewController 初始化,若 StoryBoard 中没有设置 Is Initial View Controller 必须使用 instantiateViewControllerWithIdentifier 初始化。

    • Objective-C

      1
      2
      3
      4
      5
      UIViewController *secondStoryBoardVC = [[UIStoryboard storyboardWithName:@"secondStoryBoard" bundle:nil] instantiateInitialViewController];

      UIViewController *secondStoryBoardVC = [[UIStoryboard storyboardWithName:@"secondStoryBoard" bundle:nil] instantiateViewControllerWithIdentifier:@"secondStoryBoard"];

      [self presentViewController:secondStoryBoardVC animated:YES completion:nil];
    • Swift

      1
      2
      3
      4
      5
      let secondStoryBoardVC = UIStoryboard(name: "secondStoryBoard", bundle: nil).instantiateInitialViewController()!

      let secondStoryBoardVC = UIStoryboard(name: "secondStoryBoard", bundle: nil).instantiateViewControllerWithIdentifier("secondStoryboardID")

      self.presentViewController(secondStoryBoardVC, animated: true, completion: nil)

5、StoryBoard 页面传值

  • 1)Segue 传值 - 正反传值

    • Objective-C

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      // 系统自带场景跳转相关方法
      - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

      // 1、发送方,获取输入框中的数据
      NSString *msg = _sendTextField.text;
      UIViewController *vc = segue.destinationViewController;

      // 2、发送方,发送数据,Key 与接收方设置的接收变量需一致
      [vc setValue:msg forKey:@"passData"];
      }

      // 3、接收方,声明接受数据变量,需与发送方设置的 Key 一致
      @property(nonatomic, retain)NSString *passData;

      // 4、接收方,接收数据
      _receiveLabel.text = _passData;
    • Swift

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      // 系统自带场景跳转相关方法
      override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

      // 1、发送方,获取输入框中的数据
      let msg = sendTextField.text

      let vc = segue.destinationViewController

      // 2、发送方,发送数据,Key 与接收方设置的接收变量需一致
      vc.setValue(msg, forKey: "passData")
      }

      // 3、接收方,声明接受数据变量,需与发送方设置的 Key 一致
      var passData:String?

      // 4、接收方,接收数据
      receiveLabel.text = passData
  • 2)复合传值

  • 3)单例传值

  • 4)userDefaults 传值

  • 5)代理传值

  • 6)Block/闭包 传值
文章目录
  1. 1. 前言
  2. 2. 1、StoryBoard
    1. 2.1. 1.1 StoryBoard 视图界面
    2. 2.2. 1.2 Storyboard 到代码的转换
  3. 3. 2、StoryBoard 界面设置
    1. 3.1. 2.1 启动 StoryBoard 设置
    2. 3.2. 2.2 View Controller 设置
      1. 3.2.1. 2.2.1 Identity 设置面板
      2. 3.2.2. 2.2.2 Attributes 设置面板
    3. 3.3. 2.3 View 设置
      1. 3.3.1. 2.3.1 Attributes 设置面板
  4. 4. 3、StoryBoard 关联
    1. 4.1. 3.1 添加控件代码关联
    2. 4.2. 3.2 添加 segue 关联
  5. 5. 4、StoryBoard 场景跳转
  6. 6. 5、StoryBoard 页面传值
隐藏目录