StorybookUI 1.7.0

StorybookUI 1.7.0

muukii 维护。



  • Eureka, Inc.

Swift 5.2 cocoapods cocoapods

Storybook for iOS

Storybook for iOS 是一个用于提高 UI 开发速度的库。
它使我们能够独立预览 UI 可以显示的每个组件的状态。

这个库使我们能够在大型应用中多次重建 UI 而不花费太多时间,我们可以完全构建它们而不会错过任何异常情况。

这个库受到了用于 Web 应用程序开发的 Storybook 的启发。

特性

  • 预览任何组件的每个状态,并动态更新
  • 展示任何视图控制器
  • 无限创建嵌套页面
  • 用有组织的排版标记组件
  • 声明式语法,如 SwiftUI

基本用法

设置您的书*

使用此示例组件 MyComponent 进行展示。它只是一个填充紫色色彩的盒子。

public final class MyComponent: UIView {

  public override func layoutSubviews() {
    super.layoutSubviews()

    backgroundColor = .systemPurple
  }

  public override var intrinsicContentSize: CGSize {
    .init(width: 60, height: 60)
  }
}

Book 表示 Storybook 的根。
Book 可以有一个描述自身的名字,我们可以在尾部闭包中声明其内容。

💡您需要导入 StorybookKit 模块。
此模块只提供描述书的符号。

import StorybookKit

let myBook = Book(title: "MyBook") {
  ...
}

目前我们使用 BookPreview 预览 MyComponent

let myBook = Book(title: "MyBook") {
  BookPreview {
    let myComponent = MyComponent()
    return MyComponent()
  }
}

要显示这本书,在任何视图控制器上显示 StorybookViewController。

💡您需要导入 StorybookUI 模块。
此模块提供显示书的特征。

import StorybookUI

let controller = StorybookViewController(book: myBook) {
  $0.dismiss(animated: true, completion: nil)
}

present(controller, animated: true, completion: nil)

添加组件名称

BookPreview 可以有如下的名称标签。

BookPreview {
  let component = MyComponent()
  return component
}
.title("MyComponent")

列出组件的状态

一个 UI 组件可能会有多种状态,取决于某些因素。我们可以用以下方式列出该组件的每个状态。

let myBook = Book(title: "MyBook") {
  BookPreview {
    let button = UISwitch()
    button.isOn = true
    return button
  }
  .title("UISwitch on")

  BookPreview {
    let button = UISwitch()
    button.isOn = false
    return button
  }
  .title("UISwitch off")
}

当然,您可以与这些组件交互。

动态更新组件的状态

UI组件应具备根据新的状态正确更新自己的责任。
例如,根据内容自动调整大小。

为了检查这种行为,BookPreview组件可以有一个更新组件中某些内容的按钮。

BookPreview<UILabel> {
  let label = UILabel()
  label.text = "Initial Value"
  return label
}
.addButton("short text") { (label) in
  label.text = "Hello"
}
.addButton("long text") { (label) in
  label.text = "Hello, Hello,"
}

展示ViewController

当需要检查弹出窗口时,我们使用BookPresent声明。

BookPresent(title: "Pop") {
  let alert = UIAlertController(
    title: "Hi Storybook",
    message: "As like this, you can present any view controller to check the behavior.",
    preferredStyle: .alert
  )
  alert.addAction(.init(title: "Got it", style: .default, handler: { _ in }))
  return alert
}

BookPresent(title: "Another Pop") {
  let alert = UIAlertController(
    title: "Hi Storybook",
    message: "As like this, you can present any view controller to check the behavior.",
    preferredStyle: .alert
  )
  alert.addAction(.init(title: "Got it", style: .default, handler: { _ in }))
  return alert
}

高级用法

为组织而创建指向其他页面的链接

增加组件数量,页面将会有很长的垂直滚动。
在这种情况下,Storybook为你提供了使用BookNavigationLink创建另一个页面的功能。

let myBook = Book(title: "MyBook") {
  BookNavigationLink(title: "UISwitch") {
    BookPreview {
      let button = UISwitch()
      button.isOn = true
      return button
    }
    .title("UISwitch on")

    BookPreview {
      let button = UISwitch()
      button.isOn = false
      return button
    }
    .title("UISwitch off")
  }
}

标记

我们可以添加一些描述和标题来阐明组件的实现。

let myBook = Book(title: "MyBook") {
  BookNavigationLink(title: "UISwitch") {
    BookPage(title: "UISwitch variations") {

      BookHeadline("This page previews UISwitch's state.")

      BookParagraph("""
Mainly, UISwitch has 2 states that are `on` or `off`.
This page shows you how it presents appearances in each state.
""")

      BookPreview {
        let button = UISwitch()
        button.isOn = true
        return button
      }
      .title("UISwitch on")

      BookPreview {
        let button = UISwitch()
        button.isOn = false
        return button
      }
      .title("UISwitch off")
    }
  }
}

您可以使用以下声明进行标记。

  • BookPage
  • BookSection
  • BookParagraph
  • BookHeadline
  • BookText

分离声明

随着组件数量和描述的增多,Book的声明代码也越来越长。
在这种情况下,我们可以通过几个函数来分离代码。

let myBook = Book(title: "MyBook") {
  uiswitchPage()
}

func uiswitchPage() -> BookView {
  BookNavigationLink(title: "UISwitch") {
    BookPreview {
      let button = UISwitch()
      button.isOn = true
      return button
    }
    .title("UISwitch on")

    BookPreview {
      let button = UISwitch()
      button.isOn = false
      return button
    }
    .title("UISwitch off")
  }
}

构建UI组件模式

为了检查UI组件的外观变化,这取决于输入参数,我们可以使用BookForEachBookPattern生成这些模式。

BookForEach(data: BookPattern.make(
  ["A", "AAA", "AAAAAA"],
  [UIColor.blue, UIColor.red, UIColor.orange]
)) { (args) in
  BookPreview {
    let (text, color) = args
    let label = UILabel()
    label.text = text
    label.textColor = color
    return label
  }
}

快速开发UI的项目结构

特别是在基于UIKit的应用中,检查UI变化需要很多次构建。
减少这种时间的最佳方法是为仅包含应用程序中使用到的UI组件创建单独的模块。
并为仅运行Storybook创建新的应用目标。
最后,将主应用和Storybook应用链接到该分离的模块。

当您正在调整它们时,您可以仅通过Storybook应用进行构建。

  • UIComponent(动态或静态库/框架)
    • MainApp(可执行文件)
    • StorybookApp(可执行文件)

要求

  • iOS 10.0+
  • Xcode 11.4+
  • Swift 5.2+

安装

CocoaPods

CocoaPods 是一个用于 Cocoa 项目的依赖管理器。有关使用和安装说明,请访问他们的网站。要使用 CocoaPods 将 Alamofire 集成到您的 Xcode 项目中,请在 Podfile 中指定它。

pod 'StorybookKit'
pod 'StorybookUI'

授权协议

Storybook-ios 在 MIT 许可协议下发布。