如何在不继承 SwiftUI 中其他已定义视图的情况下制作正文,苹果最初是如何做到的?

Posted

技术标签:

【中文标题】如何在不继承 SwiftUI 中其他已定义视图的情况下制作正文,苹果最初是如何做到的?【英文标题】:How can I make body without inheriting from other defined View in SwiftUI, How apple done this at first place? 【发布时间】:2021-03-21 01:17:40 【问题描述】:

我喜欢学习和学习不使用继承来创建视图,例如为了显示我的目标,我创建了一个名为 Color2 的新类型视图,它按预期工作,但实际上它继承自明确定义的 Color,所以如果我想让 Color2 独立,而不是从任何我必须创建或返回 body 的东西继承,否则 Color2 不会被 SwiftUI 编译!这更像是一个老问题先有鸡还是先有蛋?

Apple 如何让 Color 一开始就独立存在甚至存在? Apple 在做 Color View 的时候,也应该想到 Color 的本体!但是苹果只是在创造颜色,他们甚至不能像我在代码中那样继承! 因为没有要继承的颜色视图!!!

所以 问题/问题 是如何在没有符合 View 的 reference/defined View 的情况下返回 body ? (看!我想在没有鸡的情况下创建鸡蛋)

这段代码可以正常工作,它们只是伪代码:

struct ContentView: View 

    var body: some View 
        
        Color2.red
        
    


enum Color2  case red, black 

extension Color2: View 

    public var body: some View 

        switch self 
        
        case Color2.red: Color.red      // <<: Here: how can I return a View if I want not using defined View! 
        case Color2.black: Color.black  // <<: Here: how can I return a View if I want not using defined View!
 
        
    



【问题讨论】:

【参考方案1】:

所以问题/问题是如何在没有符合 View 的引用/定义 View 的情况下返回 body ?

你不能。

作为 SwiftUI 的用户,您可以这样做:

您可以通过实现body 方法来创建符合View 的类型。

您创建符合View 的类型实例并将它们传递给函数或从函数返回。

这是你做的事情:

您不会向View 询问其body

SwiftUI 框架向View 询问其body。你永远不会。

诀窍在于 SwiftUI 不会总是View 询问其 body

SwiftUI 知道一些特定的“原始”View 类型。当 SwiftUI 需要渲染(或布局)原始 View 时,它会识别出 View 是原始类型并对其进行特殊处理,无需询问原始 View 的 @987654334 @。

如果BodyNever,则View 类型是原始类型。我怎么能确定这一点?因为返回Never 类型的值是不可能!没有这样的价值观。所以,如果Viewbody 返回Never,我知道SwiftUI 不可能要求View 为其body,所以SwiftUI 必须 对待@987654344 @ 不同于“正常”View

例如,TextImageColor 都是 SwiftUI 原语:

  1> import SwiftUI
  2> Text.Body.self
$R0: Text.Body.Type = Never
  3> Image.Body.self
$R1: Image.Body.Type = Never
  4> Color.Body.self
$R2: Color.Body.Type = Never

另一方面,Rectangle 不是原语,但它的 body 返回一个未记录的原语:

  5> Rectangle.Body.self
$R3: Rectangle.Body.Type = _ShapeView<Rectangle, ForegroundStyle>
  6> _ShapeView<Rectangle, ForegroundStyle>.Body.self
$R4: _ShapeView<Rectangle, ForegroundStyle>.Body.Type = Never

您无法实现自己的原始 View 类型,因为您无权访问识别和处理原始 View 类型的 SwiftUI 实现细节。

【讨论】:

谢谢,我试过这个:import SwiftUI, Color.Body.self 然后 xcode 抱怨 are not allowed at top level,那么你在哪里找到那些代码?如果我们不允许运行这些代码,为什么它们存在? 我在 Swift REPL 中运行了我的示例:xcrun swift 从命令行。您也可以使用 Playground 进行测试。 所以用英语苹果说并允许我们自己从已经定义的视图中创建视图,换句话说,我们可以从视图中创建视图,但是我们不能像我尝试的那样定义一个全新的视图.这样说对吗? 我得到了答案,非常感谢,关于这个话题的最后一个问题!我认为我们也不允许使用原语,甚至将我们的自定义原语定义为 Xcode/SwiftUI 的用户,这被锁定并且只允许苹果本身,对吗? 您不能定义自己的原始View 类型。您只能编写现有的 View 类型。【参考方案2】:

一切都必须从某个地方开始。因此,您可以从 View 开始并撰写,如

https://www.hackingwithswift.com/quick-start/swiftui/how-to-create-and-compose-custom-views

或者你可以包装一个 UIView,如

https://www.hackingwithswift.com/quick-start/swiftui/how-to-wrap-a-custom-uiview-for-swiftui

要求更低的级别就是下拉到屏幕的像素级别,根本没有框架,这是没有意义的。您是框架的用户,而不是框架的作者

【讨论】:

那么你的回答就是说 SwiftUI 只不过是一个包装好的 UIView?!让我这么说吧:如果我们想创建一个 View,我们应该使用 SwiftUI 中定义的 View 或 Wrap a UIView,也就是说,SwiftUI 中的每一件事都只是一个 Wrapped UIView,从 Color 到 Text,从 VStack 到 Circle ?因为没有Color View可以参考!或者没有文本视图来引用它,等等。 . 不,我不是这么说的。 是的,你是说,你说在 SwiftUI 中有两种创建视图的方法! 1- 使用定义的视图 2- 使用包装的 UIView。想一想:Apple 想要为我们创建和构建 Color View 以便在 SwiftUI 中使用它,好吗?那么 Apple 只需使用包装好的 UIView 选项就可以了!因为 Apple 不能在 SwiftUI 中引用 Color View,因为它不存在!

以上是关于如何在不继承 SwiftUI 中其他已定义视图的情况下制作正文,苹果最初是如何做到的?的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI |如何覆盖 viewWillAppear 等生命周期方法

为 SwiftUI 寻找一个简单的自定义视图:picker

SwiftUI如何在更新已发布数组中的对象而不是数组本身时更新视图

SwiftUI 中自定义网格视图的额外不必要渲染问题

如何在 SwiftUI 的新地图视图中制作可点击的图钉?

如何在 SwiftUI 中添加自定义容器视图