可以选择SwiftUI和UIKit

到目前为止,你已经听说过SwiftUI了,这是一种新的、声明式的、“非常简单”的为苹果设备构建用户界面的方法。自去年发布以来,苹果开发社区一直在用文章、播客、教程和许多其他资源进行宣传。根据苹果的说法,它有可能成为“你写过的最强大的UI代码”。我们还在等什么?让我们选择swifttui,永不回头……不过话说回来,为什么不两者都选呢?

与许多长期存在的应用程序一样,OkCupid的用户使用的是几188bet金宝搏官网个不同的iOS版本。虽然旧版本的用户比例很小,但这是不可忽视的。使用SwiftUI重写用户界面所需要的工作时间也不重要。也有一些重要的可能性和结果需要考虑,比如swift tui没有相应的功能UICollectionView,这是OkCupid应用程序(以及其他许多应用程序)中大量使用的核心组件。188bet金宝搏官网

考虑到这些因素,本文将探索如何在不放弃对iOS 12和更老版本的支持的情况下明智地集成swifttui,以及首次在swifttui中构建的经验教训。在Ok188bet金宝搏官网Cupid上,我们希望开始有选择地选择某些特性,使用UIKit和SwiftUI,共享业务逻辑代码,并排构建。考虑到这一点,我创建了一个名为LoginSample的Xcode项目,以说明普通用户登录应用程序的过程。随你怎么克隆吧GitHub上的项目回购.为了简单起见,使用服务器的身份验证被使用regex的本地验证替换。与OkCupid应188bet金宝搏官网用程序一样,LoginSample支持iOS 10及以上版本。

目标

该项目的两个主要目标之一是在构建用户界面时利用共享抽象,无论它是使用UIKit还是SwiftUI构建的。主要的例子是LoginViewModel它提供配置登录视图所需的大部分值和信息。

另一个主要目标是视图应该看起来它们在屏幕上呈现的时候是一样的,行为也是一样的。

在跳

在swifttui和UIKit之间切换的第一步是创建一个视图控制器,作为swifttui或UIKit元素的容器。在这种情况下,它是LoginContainerViewController.容器的主要职责是包含一个子视图控制器和一个支持登录到应用程序的视图。版本检查用来决定显示哪个子视图控制器:

上面的代码非常简单。如果用户使用的是iOS 13及以上版本,则aUIHostingController可以使用它的根视图是SwiftUILoginView控件控制的UIKit视图LoginViewController.就像苹果公司的文档状态,UIHostingController是“当你想要将swiftuii视图集成到UIKit视图层次结构时”的完美解决方案。还包括在上面的片段是一个方便的扩展由Sundell Swifyui这使得添加子视图控制器变得很容易。

共享是关怀

慢慢地将SwiftUI与UIKit结合起来需要编写一些代码两次。这是不可避免的。用户界面的构造、配置和状态使用其各自的框架进行编码。但是,用于配置的值可以共享。通过共享来自一个源的数据,特别是LoginViewModel,只需要在一个地方进行更新,以最大限度地提高效率,并减少视图之间的差异的机会。

除了LoginViewModel,有LoginViewDelegate这是被LoginCoordinator并传递到登录视图。另一个共享依赖项是LoginDataManager,对象负责与LoginValidator决定是否创建UserLogin对象或返回一个错误以显示给用户。共享依赖关系可以从每个生命周期的开始就看到。的初始化式LoginViewLoginViewController几乎是一样的:

更仔细的观察

LoginViewModel由嵌套视图模型组成,每个模型包含用于配置登录视图的属性值:

虽然视图模型是共享的,但它并不完美。部分缺陷在于试图同时从一个来源提供两个框架所需的值。视图模型是真理的单一来源,但一些属性值的应用是不同的。此外,根据框架的不同,还有其他需要不同类型的值。这可以在仔细观察时看到LoginTextModel

字符串很容易共享,因为字符串是两个框架都使用的类型。每个视图所使用的字体可以共享,但要使用UIFont在SwiftUI,初始化字体与核心文本字体参考是必需的。这是通过铸造一个UIFont作为一个CTFont, Core Text使用的不透明类型的标识符。颜色在swifttui中可以初始化用户界面颜色.最后,一个UILabel预计numberOfLines文本使用一个lineLimit (_)

虽然分配字体可以利用免费桥接,但在其他视图模型中有一些值不能直接共享,比如堆栈视图对齐和内容模式。解决这些问题的方法是为每个协议创建一个可转换协议,该协议具有一个转换函数和将一种类型转换为另一种类型的默认实现。这种方法并不理想,我希望在我们开始并行实现特性时看到它的发展。

最后值得一提的是一个UI组件ErrorAlertView哪个是子类UIView.幸运的是,SwiftUI确实提供了一些内置的互操作性。在这种情况下,它是UIViewRepresentable,一种包装器,允许对UIView在SwiftUI视图层次结构中。ErrorAlertView可以是返回的具体类型makeUIView(背景:)只要是有类型的UIView

如果这个项目是一个功能完整的应用程序,那么在所有屏幕上显示给用户的错误视图很可能是相同的,而不仅仅是登录视图。利用UIViewRepresentable,可以使用相同的错误视图来消除两个框架的重复工作。

其他的经验教训

由于这是我第一次尝试使用SwiftUI构建一些实质性的东西,我学到了一些东西,通常是在一些尝试和错误之后。虽然项目最终实现了前面提到的目标,但还是有一些细微的差异。例如,一个文本框在swifttui中有包含占位符文本的选项,但你不能为文本指定颜色。如果仔细观察登录视图的两种呈现,您会注意到灰色略有不同。我确实遇到过一个可以叠加文本但是为了这个练习,我决定…咩。最终,我对占位符文本颜色的懒散态度并没有延伸到其他需要更多研究、毅力和对细节的关注的问题上。

向后兼容性

与任何新框架一样,漏洞比比皆是(好吧,也许不是“比比皆是”,但我很喜欢押头韵)。当我第一次尝试构建和运行LoginSample如果项目的版本低于iOS 13,应用程序就会崩溃。多亏了YichenBman的回答在堆栈溢出时,我需要做的就是添加-weak_framework SwiftUI的价值其它的链接器标志在“生成设置中链接”下。问题解决了。

向后兼容需要的另一个步骤是包括@available在导入SwiftUI的文件中封闭结构:

转换

LoginView,显示和隐藏ErrorAlert视图依赖于showError布尔属性。showError使用@State属性包装器允许修改该值。当该值被修改时,SwiftUI会销毁并重新创建视图结构,而不会丢失状态跟踪。ErrorAlert具有自定义修饰符,其中包括自定义转换,moveTopEdgeInOutWithOpacity它使用一个函数不对称(插入:删除)指定在插入和删除视图时发生的不同过渡动画。简单地说,当showError真正的,视图从顶部滑进屏幕,当它的值为,视图会滑出屏幕。

showError改变了,这工作有点像预期的,但视图跳上和离开屏幕没有过渡:

要想成功,还缺两个步骤。第一步是通过将更改包装到值来使用显式动画showError号召withAnimation ().通过改变的值showError在动画块中,SwiftUI知道动画任何视图的过渡依赖于它。请注意,withAnimation ()正在使用任何时间值改变,否则插入这种移除不会起作用。

缺少的第二步是显式设置zIndexLoginView视图层次结构。多亏了斯科特Gribben的回答在堆栈溢出时,我了解了嵌套视图在父视图层次结构中的来去zIndex并不总是一成不变的。”视图可以使用一个来插入zIndex使用另一种zIndex取决于SwiftUI如何重新绘制视图。简单地说,转变正在发生,但你可能看不到,因为zIndex是不一致的。因此,必须显式指定zIndex在整个视图层次结构中的视图:

在实现了这两个缺失的步骤之后,错误警报视图的行为就像预期的那样:

等等

最后,有两个资源对帮助我学习和完成LoginSample项目至关重要。第一个是保罗·哈德森的swift的100天,“一个免费的视频、教程、测试和更多的集合”,第二个是Vadim Bulavin的swift视图键盘回避篇文章。

结束

我真的很喜欢钻研SwiftUI并编写这个项目。尽管SwiftUI是声明式的,易于阅读,但理解和实现它仍然需要时间。有几次我对自己说,“那这个呢?你是怎么做到的?我怎么才能让这个视图与屏幕顶部垂直对齐呢?”幸运的是,Apple/Swift社区总是在那里提供帮助。我期待着这个框架的发展,特别是其他开发者如何与UIKit一起构建用户界面。正如前面提到的,你可以在GitHub上查看LoginSample项目.感谢你的阅读!

最初发表在https://tech.188bet金宝搏官网okcupid.com2020年4月27日。

188bet金宝搏官网OkCupid科技博客

阅读来自OkCupid工程团队的故事,每天连188bet金宝搏官网接着数百万人

188bet金宝搏官网OkCupid科技博客

188bet金宝搏官网OkCupid的工程团队负责每天为数百万人配对。在OkCupid科技博客上阅读他们的故事188bet金宝搏官网

乔尔

写的

188bet金宝搏官网OkCupid科技博客

188bet金宝搏官网OkCupid的工程团队负责每天为数百万人配对。在OkCupid科技博客上阅读他们的故事188bet金宝搏官网