【问题标题】:Immutable some view body variable/opaque return in View视图中不可变的某些视图主体变量/不透明返回
【发布时间】:2019-06-05 21:52:32
【问题描述】:

在 Swift 5.1 中存在不透明类型。我看到了,例如body 是必需的协议变量。它的合约定义如下:

var body: Self.Body { get }

这意味着我们应该能够将 body 标记为不可变(没有 set)。这必须怎么做?不透明的变量类型是否可能是不可变的?我试过了:

import SwiftUI

struct ContentView : View {

    init() {
        body = AnotherView(body: Text(""))
    }

    let body: some View
}

struct AnotherView: View {
    var body: Text
}

但我得到AnotherView 必须强制转换为some View 的错误。这样做之后,我得到了错误:

'some' 类型仅针对声明的属性类型实现 和下标以及函数的返回类型

我是否能够使用 some View 类型的不可变 body 变量来遵守 View(未将其显式标记为 AnotherView)? AnotherViewsome View,我不明白为什么我不能将AnotherView 的实例分配给body。我想保持灵活性并且不暴露结构体外部的实际实现类型,但我想直接在初始化器内部初始化它(因为我在初始化器内部传递值,制作更多属性并在 body 属性中使用它们是详细)。

【问题讨论】:

    标签: swift swiftui


    【解决方案1】:

    因为没有 setter,任何作为值类型的 body 实现都将是不可变的。 var 只是意味着 body 被延迟评估,而不是它是可变的。你可以声明let body,但是,正如你所指出的,这暴露了底层View的实现:

    public struct StaticTextView : View {
        public let body: Text
    
        public init(string: String) {
            self.body = Text(string)
        }
    }
    

    解决此问题的一种方法是让body 只返回一个内部私有值,如下所示:

    public struct StaticTextView : View {
        private let textView: Text
        public var body: some View { textView }
    
        public init(string: String) {
            self.textView = Text(string)
        }
    }
    

    但是,您应该记住,body 被设计为在任何绑定状态更改时动态运行,如果您想将视图分配给常量,则该视图层次结构中的任何内容都不能绑定到任何动态状态。例如,这是不可能的:

    struct DynamicStepperView : View {
        @State var stepperValue = 1
    
        var body: some View {
            Stepper(value: $stepperValue, in: 1...11, label: { Text("Current Value: \(stepperValue)") })
        }
    }
    

    如果您主要关心的是防止视图层次结构的实现细节泄漏,请注意some View 的不透明返回类型对于代码的任何客户端确实是不透明的,他们将无法看到任何除了它是一些符合View协议的东西之外的底层实现的细节。

    【讨论】:

      猜你喜欢
      • 2019-10-23
      • 1970-01-01
      • 1970-01-01
      • 2019-03-19
      • 1970-01-01
      • 1970-01-01
      • 2023-03-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多