前言

NS_CLASS_AVAILABLE_IOS(5_0) @interface UIStoryboard : NSObject
    @available(iOS 5.0, *)   public class UIStoryboard : NSObject
    NS_CLASS_AVAILABLE_IOS(5_0) @interface UIStoryboard : NSObject
    @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 视图界面

ios开发中如何在storyboard上设置button圆角_控件

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

1.2 Storyboard 到代码的转换

  • 代码编译时编译器会自动将 Storyboard 转换为相应的代码。
  • 上图设置自动转换为:
// 创建一个自定义的按钮
        UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];

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

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

        // 默认状态的背景
        [btn setBackgroundImage:[UIImage imageNamed:@"btn_01"] forState:UIControlStateNormal];
    // 创建一个自定义的按钮
        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 界面设置

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

ios开发中如何在storyboard上设置button圆角_bundle_02

  • 这个设置表明:程序启动时会加载 Main.storyboard
  • 2)View Controller 设置
  • Identity 设置面板

Custom Class

.

-- Class

StoryBoard 绑定的视图控制器

-- Module

Identity

-- StoryBoard ID

StoryBoard 的 ID

-- Restoration ID

--- Use StoryBoard ID

设置是否使用 StoryBoard ID

  • Attributes 设置面板

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

  • 3)View 设置
  • Attributes 设置面板
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> 连接的方法代码被删掉,但是连线没有去掉:
unrecognized selector sent to instance 0x7f9bf9610910libc++abi.dylib: terminating with 
    uncaught exception of type NSException
        unrecognized selector sent to instance 0x7f9bf9610910libc++abi.dylib: terminating with 
    uncaught exception of type NSException
  • 2> 连接的属性代码被删掉,但是连线没有去掉:
'NSUnknownKeyException', reason: '[<ViewController 0x7fdf7048b200> setValue:forUndefinedKey:]: 
    this class is not key value coding-compliant for the key
        'NSUnknownKeyException', reason: '[<ViewController 0x7fdf7048b200> setValue:forUndefinedKey:]: 
    this class is not key value coding-compliant for the key
  • Objective-C
// Outlet 连接
    @property (weak, nonatomic) IBOutlet UILabel *myLabel;

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

    }
    // Outlet 连接
    @property (weak, nonatomic) IBOutlet UILabel *myLabel;

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

    }
  • Swift
// Outlet 连接
    @IBOutlet weak var myLabel: UILabel!

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

    }
    // Outlet 连接
    @IBOutlet weak var myLabel: UILabel!

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

    }

3.2 添加 segue 关联

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

Relationship Segue

包含关联

show

导航推出,推出页自带返回按钮

show detail

详情推出

present modally

视图控制器之间跳转

popover presentation

视图控制器之间跳转返回

custom

自定义方式跳转

  • Objective-C
// 系统自带场景跳转相关方法,可以不写该方法
    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

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

        // 获取目标视图控制器
        UIViewController *viewController = segue.destinationViewController;
        viewController.view.backgroundColor = [UIColor orangeColor];
    }
    // 系统自带场景跳转相关方法,可以不写该方法
    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

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

        // 获取目标视图控制器
        UIViewController *viewController = segue.destinationViewController;
        viewController.view.backgroundColor = [UIColor orangeColor];
    }
  • Swift
// 系统自带场景跳转相关方法,可以不写该方法
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

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

        // 获取目标视图控制器
        let viewController = segue.destinationViewController
        viewController.view.backgroundColor = UIColor.purpleColor()
    }
    // 系统自带场景跳转相关方法,可以不写该方法
    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
// 根据 segue Identifier 跳转界面
    [self performSegueWithIdentifier:@"segueIdentifier" sender:self];
    // 根据 segue Identifier 跳转界面
    [self performSegueWithIdentifier:@"segueIdentifier" sender:self];
  • Swift
// 根据 segue Identifier 跳转界面
    self.performSegueWithIdentifier("segueIdentifier", sender: self)
    // 根据 segue Identifier 跳转界面
    self.performSegueWithIdentifier("segueIdentifier", sender: self)
  • 3)设置要跳转到的 Controller 的 StoryBoard ID,在按钮点击响应事件中添加页面跳转代码。
  • Name:StoryBoard 文件名称,Identifier:ViewController 中设置的 StoryBoard ID 名称
  • Objective-C
UIViewController *secondViewController = [[UIStoryboard storyboardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:@"storyboardID"];

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

    [self presentViewController:secondViewController animated:YES completion:nil];
    UIViewController *secondViewController = [[UIStoryboard storyboardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:@"storyboardID"];

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

    [self presentViewController:secondViewController animated:YES completion:nil];
  • Swift
let secondViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("storyboardID") 

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

    self.presentViewController(secondViewController, animated: true, completion: nil)
    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
UIViewController *secondStoryBoardVC = [[UIStoryboard storyboardWithName:@"secondStoryBoard" bundle:nil] instantiateInitialViewController];

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

    [self presentViewController:secondStoryBoardVC animated:YES completion:nil];
    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
let secondStoryBoardVC = UIStoryboard(name: "secondStoryBoard", bundle: nil).instantiateInitialViewController()!

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

    self.presentViewController(secondStoryBoardVC, animated: true, completion: nil)
    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
// 系统自带场景跳转相关方法
    - (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;
    // 系统自带场景跳转相关方法
    - (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
// 系统自带场景跳转相关方法
    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
    // 系统自带场景跳转相关方法
    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/闭包 传值