视图中不可变的某些视图正文变量/不透明返回



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

var body: Self.Body { get }

这意味着我们应该能够将身体标记为不可变(没有set)。必须如何做到这一点?不透明变量类型是否有可能不可变?我试过了:

import SwiftUI
struct ContentView : View {
init() {
body = AnotherView(body: Text(""))
}
let body: some View
}
struct AnotherView: View {
var body: Text
}

但是我得到一个错误,AnotherView必须投射到some View.这样做之后,我收到错误:

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

我是否能够符合View类型为some View的不可变body变量(不将其显式标记为AnotherView)?AnotherViewsome View,我不明白为什么不能将AnotherView的实例分配给body。我想保持灵活性,不要在结构体外部公开主体的实际实现类型,但我想直接在初始值设定项中初始化它(因为我在初始值设定项中传入值,创建更多属性并在 body 属性中使用它们是冗长的)。

因为没有资源库,所以任何作为值类型的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协议的某些东西之外,它们将无法看到底层实现的任何详细信息。

最新更新