在没有UIView的情况下构建UI

在约翰·桑德尔(John Sundell)在Scale上播放的精彩视频的鼓舞下,我决定写更多有关组件驱动的UI,为什么要这么做以及如何做(针对iOS)的文章。

我将在另一篇文章中向您介绍LeeGo,并向您展示如何使用它制作组件驱动的本机UI。 但是,现在,我将尝试仅关注最基本的想法。

毕竟,让我们花一分钟…

只需考虑一下我们通常如何在iOS中设置UI。

无论使用或不使用Interface Builder,我们始终需要使用UIView实例。 要么手动设置视图框架,要么使用自动布局,我们总是需要添加一个UIView实例作为子视图。 无论是使用标准的自动布局API还是使用精美的第三方自动布局助手库,我们都始终将UILayout实例设置为自动布局约束。

问题是:在iOS中处理UI时, 总是存在UIView实例,该实例繁重,易变且需要主线程。

作为后果:
–我们必须处理一堆冗长的代码或一堆IB文件,或两者。
–很难重复使用该代码,必须一次又一次重复类似的代码或IB文件。
–我们必须经常将UI配置逻辑从同一组件分离到不同的位置:一部分在IB文件中,其余部分在代码中。

随着复杂性的增加,这些问题最终将导致维护的噩梦。

通过摆脱UIView实例,开始重用UI中的所有内容

在讨论如何摆脱` UIView`实例之前,让我们进一步了解一下UI组件。

UI组件剖析

几乎所有UI组件(例如视图,标签,图像视图或其他内容)都可以分离,并分为5部分描述:
1.类型–哪一类? UIView或其子类。 这是定义UI组件所必须要做的唯一一件事。

2.名称-重用组件时的名称是什么? 组件需要一个名称才能重用。 名称可以代表该组件的性质。 例如“标题”,“字幕”,“头像”,“ likeButton”,“ favoriteButton”,“ subscriberButton”,“ date”等。

3.样式–组件本身的外观如何? 它可以是视觉外观,例如“ backgroundColor”,“ numberOfLines”,也可以是非视觉视图属性,例如“ userInteractionEnabled”,“ scrollEnabled”。 样式几乎总是可以键/值转换的,可以轻松地放入字典中。

4.子组件–父组件内部是什么? 它肯定是另一个UI组件,因此也可以以相同的方式递归地对其进行描述。 这意味着我们只需要子组件的名称即可在以后检索它。

5.布局–如何安排孩子? 如果有多个子组件,我们将需要一个布局。 这是棘手的部分。 我们不能通过手动设置框架或使用自动布局来避免UIView实例。 幸运的是,Apple还为我们提供了另一种方式:视觉格式语言。 VFL使我们可以用纯ASCII定义整个布局。

  let layout = [“ H:| -20- [title] -10- [avatar] -20- |”,“ V:| -20- [title] -10- [subtitle] -20- |”] 

您可能还没有注意到,我们已经拥有定义整个UI所需的一切, 而没有UIView实例,这里只有值类型 。 此外,每个组件的名称都可以重用。 所有样式和布局也将可重用。

……就是这样。 这就是全部:现在,我们的UI没有单个UIView实例。 🎉

我们现在有什么?

  • 我们可以从任何位置定义整个UI,所有UI逻辑都可以集中在一个地方。
  • 所有组件都有现货供应,因此我们可以在需要时重新使用它们。
  • 由于现在所有事物都是值类型,这意味着它们完全是线程安全的。 因此,我们可以轻松地在后台计算和操纵UI层次结构。
  • 由于每件事都是键/值可转换的,因此它还提供了通过JSON负载从后端驱动朴素UI的功能。

想想乐高积木

现在,我们需要做的是分析应用程序的所有屏幕,将它们解耦并仔细命名为小块的UI组件。 这个想法和乐高积木一样。

每个组件的作用都与乐高积木完全相同。 它可以是简单的砖,也可以不与其他砖混合。

它也可以是由许多不同结构的不同简单砖组合而成的超级复杂单元。

下一步是什么 ?

如开头所述,在另一篇文章中,我将通过LeeGo的代码和示例向您详细介绍如何执行组件驱动的UI。