[Translation] SwiftUI in 2021: Strengths, weaknesses and pitfalls

SwiftUI in 2021: Strengths, Weaknesses, and Pitfalls

Using SwiftUI in production? Still not feasible.

Posted by Maxwell Nelson on Unsplash

For the past 8 months, I've been developing complex apps in SwiftUI, including Fave , which was recently launched on the App Store . During this period, many limitations were encountered, and solutions to most problems were found.

In short, SwiftUI is a great framework and very promising. I think it's the future. But it may take another 3-5 years to reach the same reliability and robustness as UIKit. But that doesn't mean SwiftUI shouldn't be used now. My goal is to help you understand its pros and cons so you can make a more informed decision about whether SwiftUI is right for your next project.

Advantages of SwiftUI

1. Writing SwiftUI is a joy, and you can build user interfaces quickly

Gone are the days of carefully calculating the size and position of controls, wrestling with pesky constraint issues, and manually building view hierarchies using and addSubview. sizeForItemAtIndexPathSwiftUI's declarative and responsive design patterns make creating responsive layouts as easy as React, while backing Apple's powerful UIKit. It's unbelievably fast to build, get up, and run views.

2. SwiftUI simplifies cross-platform development

The thing I'm most excited about is writing SwiftUI code once and using it on iOS (iPhone and iPad), WatchOS and macOS. Developing and maintaining separate code bases for Android and Windows at the same time is already difficult, so every small change helps in reducing the number of different code bases. Of course, there are still some disadvantages, which I will share in the "Disadvantages" section.

3. You can get beautiful transitions, animations and components for free

You can think of SwiftUI as a UI toolkit that provides all the building blocks needed to develop professional applications. In addition, if you are familiar with the Transition property of CSS, you will find that SwiftUI also has a set of similar methods, which can easily create an elegant interaction process. The charm of declarative syntax is that you only need to describe what effect you need, and the effect will be realized. This seems like magic, but it also has a bad side, which I will introduce later.

4. The UI is fully state-driven and responsive

If you're familiar with React, SwiftUI is completely similar in this regard. When you listen to the entire UI for "reactions", animations and all, you only need to modify the @Stateand @Bindingand @Publishedproperties instead of using dozens of layers of nested callback functions. With SwiftUI, you can experience the power of Combine, andObservableObject . @StateObjectThis aspect is one of the coolest differences between SwiftUI and UIKit, and it's incredibly powerful.

5. The community is embracing SwiftUI

几乎每个人都在因为 SwiftUI 而兴奋。SwiftUI 有许多学习资源可供获取,从 WWDC 到书,再到博客 —— 资料就在那里,你只需要去搜索它。如果不想搜索的话,我这里也汇总了一份最佳社区资源列表。

拥有一个活跃且支持度高的社区可以加速学习,开发,并且大量的新库会使得 SwiftUI 用途更加广泛。

劣势

1. 不是所有组件都可以从 SwiftUI 中获取到

在 SwiftUI 中有许多缺失、不完整或者过于简单的组件,我将在下面详细介绍其中一部分。

使用 UIViewRepresentableUIViewControllerRepresentableUIHostingController 协议可以解决这一问题。前两个让你可以在 SwiftUI 视图层中嵌入 UIKit 视图和控制器。最后一个可以让你在 UIKit 中嵌入 SwiftUI 视图。在 Mac 开发中也存在类似的三种协议 (NSViewRepresentable 等)。

这些协议是弥补 SwiftUI 功能缺失的权宜之计,但并不是一直天衣无缝。而且,尽管 SwiftUI 的跨平台承诺很好,但是如果某些功能不可用的话,你仍然需要为 iOS 和 Mac 分别实现协议代码。

2. NavigationView 还没有真正实现

如果你想在隐藏导航栏的同时仍然支持滑动手势,这是不可能的。我最终参考一些找到的代码创建了一个 UINavigationController wrapper。尽管可以起作用,但这不是一个长远的解决方案。

如果你想要在 iPad 上拥有一个 SplitView,但目前你还不能以纵向模式同时展示主视图和详情视图。他们选择用一个简陋的按钮展示默认关闭的抽屉。显然,你可以通过添加 padding 来解决这个问题,它可以突出显示你在使用 SwiftUI 时必须做的事情。

当你想使用编程式导航的时候,NavigationLink 是一种流行的解决方案。这里有一个有趣的讨论

3. 文本输入十分受限

TextFieldTextEditor 现在都太简单了,最终你还是会退回到 UIKit。所以我不得不为 UITextFieldUITextView 构建自己的 UIViewRepresentable 协议(以实现文本行数的自动增加)。

4. 编译器困境

当视图开始变得笨重,并且你已经竭尽所能去提取分解,编译器仍然会冲着你咆哮:

The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions.

这个问题已经多次拖慢进度。由于这个问题,我已经很擅长注释代码定位到引起问题的那一行,但是 2021 年了还在用这种方法调试代码感觉非常落后。

5. matchedGeometryEffect

我第一次发现这个的时候,感觉很神奇。它目的是通过匹配一隐一现的几何形状,帮助你更加流畅地转换两个不同标识的视图。我觉得这有助于从视图 A 优雅地转场到 B 视图。

我一直想让它起作用。但最终还是放弃了,因为它并不完美。此外,在包含大量列表项的 ListScrollView 中使用它会导致项目瘫痪。我只推荐在同一视图中使用这个做简单的转换过渡。当你在多个不同的视图中共享一个命名空间的时候(包括转场期间的视图剪裁在内),事情就会开始变得奇怪。

6. 对手势的支持有限

SwiftUI 提供了一系列新的手势(即 DragGestureLongPressGesture)。这些手势可以通过 gesture 修饰符(如 tapGesturelongPressGesture)添加到视图中。它们都能正常工作,除非你想要做更复杂的交互。

比如,DragGestureScrollView 交互就不是很好。即使有了 simultaneousGesture 修饰符,在 ScrollView 中放一个 DragGesture 还是会阻止滚动。在其他情况下,拖动手势可以在没有任何通知的情况下被取消,使得手势处于不完整状态。

为了解决这个问题,我构建了自己的 GestureView,它可以在 SwiftUI 中使用 UIKit 手势。我会在下一篇关于最佳 SwiftUI 库和解决方案的文章中分享这部分内容。

7. 分享扩展中的 SwiftUI

我可能是错的,但是分享扩展还是使用 UIKit 吧。我通过 UIHostingController 用 SwiftUI 构建了一个分享扩展,当分享扩展加载完毕后,有一个非常明显的延迟,用户体验较差。你可以尝试通过在视图中添加动画去掩盖它,但是仍然有 500 毫秒左右的延迟。

值得一提的点

  • 无法访问状态栏 (不能修改颜色或拦截点击)
  • 由于缺少 App,我们仍然需要 @UIApplicationDelegateAdaptor
  • 不能向后兼容
  • UIVisualEffectsView 会导致滚动延迟(来源于推特:@AlanPegoli

缺陷

1. ScrollView

这是迄今为止最大的缺点之一。任何一个构建过定制化 iOS 应用的人都知道我们有多依赖 ScrollView 去支持交互。

  • 主要的障碍:视图中的 LazyVStack 导致卡顿、抖动和一些意外的行为LazyVStack 对于需要滚动的混合内容(如新闻提要)的长列表至关重要。仅凭这一点,SwiftUI 就还没准备好投入生产环境: Apple 已经证实,这是 SwiftUI 自身的漏洞。尚未清楚他们什么时候会修复,但是一旦修复了,这将是一个巨大的胜利。
  • 滚动状态:原生不支持解析滚动的状态(滚动视图是否正在被拖拽?滚动?偏移多少?)。尽管有一些解决方案,但是还是很繁琐且不稳定。
  • 分页:原生不支持分页滚动视图。所以打消实现类似于可滑动的媒体库的念头吧(但是如果你想要关闭一些东西的时候,可以使用 SwiftUIPager)。在技术上你可以使用 TabViewPageTabViewStyle,但是我认为它更适合少部分的元素,而不是大的数据集。
  • 性能:使用 List 是性能最好的,并且避免了 LazyVStack 的卡顿问题,但由于工作方式的转换,它仍然不适合显示可变大小的内容。例如,在构建聊天视图时,其过渡很奇怪,会裁剪子视图,并且无法控制插入的动画样式。

结论

毫无疑问我觉得应该学习 SwiftUI ,自己去理解它,并享受乐趣。但是先别急着全盘采用。

SwiftUI 已经为简单的应用程序做好了准备,但是在写这篇文章的时候(iOS 15,beta 4 版本),我不认为它已经适合复杂应用程序的生产环境,主要是由于 ScrollView 的问题和对 UIViewRepresentable 的严重依赖。我很遗憾,尤其是像即时通信产品,新闻摘要,以及严重依赖复杂视图或者想要创建手势驱动的定制体验产品,目前还不适合使用 SwiftUI。

如果你想要精细的控制和无限的可能性,我建议在可预见的未来坚持使用 UIKit。你可以在一些视图(如设置页)里通过使用 UIHostingController 包装 SwiftUI 视图以获得 SwiftUI 的好处。

未来会发生什么?

当开始着手我们项目的下一次大迭代的时候。我知道这个新项目的交互范围不在 SwiftUI 目前支持的范围之内。即使当我知道 SwiftUI 在某些关键方面存在不足的时候,我的心都碎了,但是我还是不打算退回到 UIKit,因为我知道当 SwiftUI 运行起来时,构建它是一件多么快乐的事情。它的速度如此之快。

SwiftUI 会兼容 UIKit 么?如果这样的话,我们可能需要等待 SwiftUI 使用 3-5 年的时间来移植所有必要的 UIKit API。如果 SwiftUI 不准备兼容 UIkit,那你也能通过 SwiftUI 封装的方式使用 UIKit。

我好奇的是 Apple 会在 SwiftUI 上投入多少。他们是否有让所有的开发者采用 SwiftUI 的长期计划,或者说 SwiftUI 只是另一个界面构建器而已?我希望不是,也希望他们能全心投入 SwiftUI,因为它的前景是非常诱人的。

更多看法

如果发现译文存在错误或其他需要改进的地方,欢迎到 掘金翻译计划 对译文进行修改并 PR,也可获得相应奖励积分。文章开头的 本文永久链接 即为本文在 GitHub 上的 MarkDown 链接。


The Nuggets Translation Project is a community for translating high-quality Internet technical articles. The source of the articles is the English shared articles on Nuggets. The content covers Android , iOS , front-end , back- end , blockchain , product , design , artificial intelligence and other fields. If you want to view more high-quality translations, please continue to pay attention to the Nuggets Translation Project , official Weibo , and Zhihu column .

Guess you like

Origin juejin.im/post/7140825514108780580