0

在 Swift 5.1 中有不透明的类型。我看到 egbody是必需的协议变量。它的合同定义如下:

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' 类型仅针对属性和下标的声明类型以及函数的返回类型实现

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

4

1 回答 1

1

因为没有 setter,所以任何body值类型的实现都是不可变的。varjust 意味着被懒惰地评估,而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-06-06T13:51:26.293 回答