在 SwiftUI 中显示和隐藏视图

时间:2021-05-07 02:39:35

标签: ios swift swiftui

我想在任务完成时显示一个视图,我还能如何调用 SwiftView 来显示而不使用基于 State bool 的条件?基本上我想避免在下面为每个需要加载视图的文件进行硬编码...

chart.colors = [
  {
    backgroundColor: "#0f0",
    pointBackgroundColor: "#000",
  },
  {
    backgroundColor: "#f0f",
    pointBackgroundColor: "#00f",
  },
  {
    backgroundColor: "#ff0",
    pointBackgroundColor: "#f00",
  },
]; 

1 个答案:

答案 0 :(得分:0)

您可以探索一些减少重复代码的策略。

  1. 自定义环境值以避免传递@Binding
  2. 可重复使用的效果
  3. 如果您的状态很复杂(可能不是),则可能是一个协议

改变视图层次结构

自定义 EnvironmentValue 将状态广播到子视图。这将使您免于通过可能不消耗该值的视图传递 @Binding。

请记住,这是一种自上而下的单向广播。与@Binding 不同,孩子不能改变父状态。 (但他们可以改变自己孩子对所述状态的了解。)

在父级中设置

@State var isHovered = false

var parent: some View {
///
  .environment(\.parentIsHovered, isHovered)
}

观察儿童

@Environment(\.parentIsHovered) var parentIsHovered

var child: some View {
///
   .grayscale(parentIsHovered ? 0 : 0.9)
   .animation(.easeInOut, value: parentIsHovered)
}

定义

private struct ParentIsHoveredKey: EnvironmentKey {
    static let defaultValue: Bool = false
}


extension EnvironmentValues {
    
    var parentIsHovered: Bool {
        get { return self[ParentIsHoveredKey] }
        set { self[ParentIsHoveredKey] = newValue }
    }
}

可重复使用的效果

如果您使某些视图变灰或显示加载指示器,则可以使用接受 Binding 并有条件地显示叠加层、背景或效果的 ViewModifier。

下面的示例通过将 .animation API 链接到 accessibilityReduceMotion 来演示这一点。

// view
    .animate(.easeOut(duration: .fast), value: isLoading)


extension View {
    func animate<E: Equatable>(_ animation: Animation?, value: E) -> some View  {
        self.modifier(AccessibleAnimationModifier(animation, for: value))
    }
}

struct AccessibleAnimationModifier<E: Equatable>: ViewModifier {
    
    @Environment(\.accessibilityReduceMotion) var reduceMotion
    
    init(_ animation: Animation? = .default, for value: E) {
        self.animation = animation
        self.value = value
    }
    
    var animation: Animation?
    var value: E
    
    func body(content: Content) -> some View {
        content
            .animation(reduceMotion ? .none : animation, value: value)
    }
}

对加载状态做出反应

除非您通过某个观察到的类处理加载状态,否则您需要使用@State 将该状态存储在您的视图中。

也许在扩展中具有默认实现的协议有助于减少计算视图之间复杂加载状态时的重复代码。

下面的伪代码定义了一个带有返回 NSItemProvider 函数的 DragSource 协议。该扩展提供了 View 或 VM 可以调用的默认实现。

protocol DragSource {
    
    func makeDraggableThing1(/// content + logic objects) -> NSItemProvider

}

extension DragSource {
    
    func makeDraggableThing1(///) -> NSItemProvider {
        /// Default work I only want to edit once in the app
    }
}

相关问题