首发于 小专栏 https://xiaozhuanlan.com/topic/6920751348

前言

Xcode Library 最早是作为 Storyboard (xib)的配套功能引入。在制作 Storyboard 时,开发者打开右下角的 Object Library,从中选择合适的组件,通过拖拽快速引入组件对象。它和所有可视化搭建系统一样,是组件展示区,方便开发者快速浏览引入。后面的 Xcode 版本慢慢引入了色盘、图片资源等功能,到 Xcode10 时, Object Library 的重要性进一步提高,位置从右下角可能被隐藏的位置提升到 Xcode 右上角功能 toolbar 按钮区,常驻界面。到了 Xcode11, Object Library 升级为 Library,成为添加某些对象等的总入口,包括代码片段、文档。

很多人没有意识到,Library 其实是上下文相关,例如如果你在编辑 Storyboard 则显示 Object、Color、Image Library,image;如果正在选中 xproj 文件,则显示添加 Capability 快捷入口,image;选中 .swift 源文件,则显示 Views、Code Snippets等image Xcode Libary 提供了一种发现学习可视化操作视图、组件、应用 api 的快捷途径。它左侧列表展示 Libary 所有可用对象等,选中后在右侧会展示相应的文档说明和举例;顶部提供了快速搜索,支持模糊查询和组合查询,非常的高效。

总之,打开 Library “+”(快捷键- Shift + Command + L)逐渐进化为搜索、引用的总入口,如同 macOS 上的 Alfred、Sublime Text 里的 Shift + Command + P 一样。

小贴士:引入 Library 里的 Object 到文件有两种方式,1. 拖拽至目标位置;2.放置光标在目标位置,双击 Object。

SwiftUI 开发过程中常用的 View 和 Modifier 如果被添加到 Library 将极大的提高开发效率,在 Xcode 11 里你可以添加自定义 Code Snippet,但不能新增新的 Object,在 Xcode 12 你可以在 View Library 下添加自定义的 View。下面演示如何添加自定义 View 和自定义 Modifier。

准备工作

为了演示效果,我编写一个简单的列表页展示近期可能上映的 5 部电影,分别显示上映电影名称、时长、片子类型,其中如果是恐怖片、悬疑片、科幻片则显示红心,表示很期待。详细代码见附件,最终效果如下; image

理念

SwiftUI 面世之初,它的设计理念贯彻着代码即原型——开发者的代码即时预览在 Canvas 里,可作为 App 原型呈现给产品、交互作为具象参考;Xcode 12 之后,又带来了代码即文档,代码即 demo 新体验。在 Library 里自定义 view 的增减变动和代码实现、文档变动,时刻保持最新。在日常开发者,经常会遇到第三方库的开发文档、注释过时的情况。举个我最近遇到的例子,我从腾讯云下载的 OCR demo 里使用的 SDK 和他单独提供最新版本的 OCR 版本就不一样,开发文档也是旧的没更新。 使用 Library 添加 SwiftUI 自定义组件、接口说明,就不会有这种情况出现。

提炼公用 view 组件

虽然本 session 里强调是容许在工程开始之初,不需要编译,就可以创建 Library 对象,但是实际情况大部分都是重构的时候,发现某些元素是公用组件,然后提炼出来,添加到 Library,方便后续开发使用。在本文里,我们假设两种“最爱”的红心是公用组件。现在我们准备把他们添加到 Library 里。

创建自定义 LibraryContentProvider

LibraryContentProvider是 Protocol,Xcode 会扫描当前 project/workspace/Swift Pacage 所有文件里的 LibraryContentProvider 实例,添加到 Library 里。语法如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
struct SimpleFavoriteContent: LibraryContentProvider {
    @LibraryContentBuilder
    var views: [LibraryItem] {
        LibraryItem(
            HStack{
                Spacer()
                Image(systemName: "heart.fill").foregroundColor(.red)
            },
            title: "Red heart in right",
            category: .control
        )
    }
}

其中 category 是为了在打开的 Library 左侧列表中分组;title 是对组件的描述,用来做不同组件区分。可惜的是,我们的自定义组件,选中后右侧没有显示对应的代码示例,而系统内置的 View 是有的。查阅了 LibraryItem 的接口,没有找到可定义的地方。添加完毕之后和实现的效果如图。 image

小贴士: title 不要用中文,搜索起来不方便。

创建自定义 Modifier

相比自定义 View,Modifier 可能的数量会非常多,也是最可能玩出花的地方。为了展示,我引入了 SwiftUI-CSS 库,核心代码如下(详细代码见 demo)

1
2
3
4
5
6
7
8
// 定义评论的样式
let comments_clsName = CSSStyle([
    .font(.footnote),
    .paddingEdges([.top], 2.0),
    .foregroundColor(.blue)
])
// 引用样式
Text("“\(m.comments!)“").addClassName(comments_clsName)

在 session 的举例中,是为 Image 添加了个 extension ,新增一个方法设置样式,然后将此方法设置为 Modifier Library 对象。本文我们用 SwiftUI-CSS 来设置样式,其代码添加到 Library。自定义 View 和 Modifier 的接口方式不一样。一个是属性,一个是 function 回调,因为 Modifier 需要传入参数,而自定义 View 不需要。 以下是添加自定义 Modifier 的步骤,新建 func modifiers,设置 title 和 category。

1
2
3
4
5
6
7
8
@LibraryContentBuilder
    func modifiers(base: Text) -> [LibraryItem] {
        LibraryItem(
            base.addClassName(comments_clsName),
            title: "Comment style",
            category: .effect
        )
    }

添加完毕的效果: image 可以看到,同样比较遗憾的是,无法添加注释和示例(系统的是有的)。LibraryItem 里的 category 属性,如果是自定义 Modifier 则设置为 .control 是无效的。

至此,如何添加自定义 View 和 Modifier 已经演示完了。这里有几个问题,目前 Library 还没很好支持的。

  1. 自定义 Modifier 和 View 都无法添加注释和代码样例
  2. 两个相近的自定义 View (例如,我们在编写基于 tableView 的界面时,需要设置 Cell 的 style , UITableViewCellStyleValue1 和 UITableViewCellStyleValue2 两种),你每次使用时,是不是都会很犹豫,到底用哪个?,如果自定义 View 能够在 Library 右侧顶部能够显示,该 View 的预览图是不是更好、更直观?另外 Library 声称不需要整个项目能够 run 起来就可以添加到 Library,其实是个不好的妥协。就应该把 Library 作为可预览前置条件的一部分。我画个假想图; image image

LibraryContentProvider 作为开发阶段工具链的一部分代码,通过上传到 git,可以形成大家共用的组件库;良好定义的 Modifier 可以组装成一致的视觉样式系统,提升视觉稿实现代码的速度和视觉还原度。而且在 release 包里这些开发工具链上的代码内容都会被删除。

更进一步,所有从 Swift Package 里定义的 LibraryContentProvider 子类(View 和 Modifier)都会显示在 Xcode Library 里,这是一种简单的引用第三方组件、样式的途径,非常棒。总之,善用 Xcode Library 可加速开发效能,大家用起来吧。

参考

  1. https://stackoverflow.com/questions/50962797/where-did-the-object-library-go-in-xcode-10
  2. https://github.com/hite/swiftui-css
  3. https://github.com/hite/WWDC20