视图中不可变的某些视图主体变量/不透明返回

Posted

技术标签:

【中文标题】视图中不可变的某些视图主体变量/不透明返回【英文标题】: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 属性中使用它们是详细)。

【问题讨论】:

【参考方案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协议的东西之外的底层实现的细节。

【讨论】:

以上是关于视图中不可变的某些视图主体变量/不透明返回的主要内容,如果未能解决你的问题,请参考以下文章

python中不可变的组合数据类型

python中不可变数据类型和可变数据类型

python中不可变数据类型和可变数据类型

从子视图中更改视图中的数组“不能在不可变值上使用变异成员:'self' 是不可变的”

Python中不可变类型和可变类型详解

Python中不可变类型和可变类型详解