javafx树视图加选框
We already saw in a previous article how common optional views are. We also saw that the logic handling the optionality can have different owners. Finally, we saw how to implement reusable optional views with Swift + UIKit.
我们已经在上一篇文章中看到了常见的可选视图。 我们还看到处理可选性的逻辑可以具有不同的所有者。 最后,我们看到了如何使用Swift + UIKit实现可重用的可选视图。
This time, we are going to skip the introduction and go straight into how to do the same thing with SwiftUI using an example.
这次,我们将跳过一个介绍,并直接通过一个示例直接介绍如何使用SwiftUI执行相同的操作。
进入高级小部件 (Go Premium Widget)
Let’s say we have a freemium app where users do not need to pay to use the app, but we want to make them well aware of our premium plan that includes additional features.
假设我们有一个免费增值应用,用户无需付费即可使用该应用,但我们想让他们充分了解我们的高级计划,其中包括其他功能。
We are going to show a “Go Premium” widget on different parts of the app where they can tap to launch the process. But Go Premium widgets should not be shown when users are already premium for obvious reasons.
我们将在应用程序的不同部分上显示一个“ Go Premium”小部件,他们可以点击以启动该过程。 但是,由于明显的原因,当用户已经是高级用户时,不应显示Go Premium小部件。
Let’s start by showing the Go Premium widget in a non-optional way. We will use a simple Text
so we do not get lost in details:
让我们以非可选方式显示Go Premium小部件开始。 我们将使用一个简单的Text
以免丢失细节:
使小部件成为可选 (Making the Widget Optional)
In order to turn the widget optional, we need to do a few changes.
为了将小部件设为可选,我们需要做一些更改。
We start by extracting the widget’s instantiation out of ContainerView
and using a protocol so we can inject it:
我们首先从ContainerView
提取小部件的实例化并使用协议,以便将其注入:
And now we can refactor the view
property so it returns either self
or EmptyView
depending on whether the user is already premium or not.
现在我们可以重构 view
属性,以便根据用户是否已经付费而返回self
或EmptyView
。
There’s a problem with the view
property’s return type, though, because SwiftUI.View
cannot be used as the abstraction of PremiumWidget
. It uses Self
, so it cannot be used as a type. We cannot return some View
either because opaque types cannot be the return type of a protocol requirement.
但是, view
属性的返回类型存在问题,因为SwiftUI.View
不能用作PremiumWidget
的抽象。 它使用Self
,因此不能用作类型。 我们也不能返回some View
,因为不透明类型不能是协议要求的返回类型。
Fortunately, SwiftUI provides at least a couple of ways to do this. One is using a type-erased view — AnyView
. Another approach is using Group. Some claim that AnyView
has performance implications, but you should read this article first and then make your own decision. Anyway, we are going to show how it can be done with AnyView
, but feel free to use either of them. The differences in code should be minimal.
幸运的是,SwiftUI提供了至少两种方法来执行此操作。 一种是使用一种类型的擦除视图- AnyView
。 另一种方法是使用Group 。 有人声称AnyView
性能产生影响,但是您应该先阅读本文 ,然后再做出自己的决定。 无论如何,我们将展示如何使用AnyView
做到这一点,但是请随时使用它们中的任何一个。 代码上的差异应最小。
Now we have an optional widget based on the condition of the user being premium or not, but there are a few significant issues here:
现在,我们根据用户是否为高级用户的条件提供了一个可选的小部件,但是这里有一些重要的问题:
PremiumWidget
is being instantiated either way.两种方法都可以实例化
PremiumWidget
。The
PremiumWidget
class should not own the responsibility of knowing when to be shown or not.PremiumWidget
类不应该负责知道何时显示或不显示。
提取实例化到工厂类 (Extracting Instantiation to a Factory Class)
We are going to move the instantiation of PremiumWidget
to a factory class while taking into account these premises:
考虑到以下前提,我们将把PremiumWidget
的实例化为工厂类:
Since we already extracted
PremiumWidget
’s instantiation,ContainerView
should not be modified.由于我们已经提取了
PremiumWidget
的实例,因此不应修改ContainerView
。We do not want to make
ContainerView
aware that we are using a factory class.我们不想让
ContainerView
知道我们正在使用工厂类。
This is why we are going to use the proxy pattern:
这就是为什么我们要使用代理模式的原因 :
Since both PremiumWidget
and PremiumWidgetFactory
conform to PremiumWidgetProtocol
, we can inject either of them without ContainerView
knowing which one is being used. This will allow us to remove the optionality without changing any container where PremiumWidget
is being used.
由于PremiumWidget
和PremiumWidgetFactory
符合PremiumWidgetProtocol
,因此我们可以在不让ContainerView
知道使用哪一个的情况下注入它们中的任何一个。 这将使我们能够删除可选项,而无需更改使用PremiumWidget
任何容器。
This might not make a lot of sense in the concrete example of a PremiumWidget
, but it would in cases such as A/B testing, optional features that can become non-optional, etc.
在PremiumWidget
的具体示例中,这可能没有多大意义,但是在诸如A / B测试,可选功能(可能变为非可选)等情况下,这可能没有多大意义。
结论 (Conclusion)
Thank you for reading. Let me know what you think.
感谢您的阅读。 让我知道你的想法。
Thanks to Raul Menezes for reviewing the article and suggesting the use of EmptyView
instead of optionals.
感谢Raul Menezes审阅了这篇文章并建议使用EmptyView
而不是可选的。
翻译自: https://medium.com/better-programming/optional-views-with-swiftui-ab551030296d
javafx树视图加选框