Text 或 Image 等视图类型如何符合 SwiftUI 中的 View 协议?
How do view types like Text or Image conform to the View protocol in SwiftUI?
关于 SwiftUI 中的视图类型,有一件大事让我感到困惑:
它们似乎不符合 View
协议,但不知何故,它们神秘地符合。
以Text
类型为例。定义如下:
public struct Text : Equatable { ... }
我找不到任何 public 扩展符合 View
协议,例如
extension Text: View { ... }
和 official documentation 中的 Relationships 部分简单地指出:
Conforms To: Equatable
仅此而已。
然而,我可以 return 一个 Text
的实例,其中需要一些 View
,例如:
var body: some View {
Text("I'm a View, I swear!")
}
如果 Text
不符合 View
,这是不可能的,并且会抛出编译器错误。
(some View
是一个 不透明的结果类型 这意味着它是一种具有身份的特定类型,但符合 View
.)
这怎么可能?
为 SwiftUI 视图类型指定的 View
协议一致性在哪里(如 Text
、Image
、Circle
、 ...)?
如您所知,有 2 种类型是视图..
- 原始视图:
Text
、Image
、Circle
等
- 容器视图:
List
、HStack
、VStack
等
也就是说,下面是 Text
的扩展,Body 设置为 Never,这意味着它不允许有 body,因为它是一个原始视图,用于结束 body 循环。
因此,(根据我的理解)SwiftUI 在运行时发现原始视图不在容器视图内时将 Text
包装在容器视图内。
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
extension Text {
/// The type of view representing the body of this view.
///
/// When you create a custom view, Swift infers this type from your
/// implementation of the required `body` property.
public typealias Body = Never
}
SwiftUI 视图类型符合 View
协议,否则如您所述,代码将无法编译。我发现其中一些在 SwiftUI public 扩展中可用:
Image
类型有一个直接符合 View
:
的扩展
extension Image : View {
}
Circle
符合 Shape
,后者本身符合 View
:
public struct Circle : Shape {
...
}
public protocol Shape : Equatable, Animatable, View {
...
}
扩展。
extension Text : View {
/// The type of view representing the body of this view.
///
/// When you create a custom view, Swift infers this type from your
/// implementation of the required `body` property.
public typealias Body = Never
}
这个问题是在 2019 年 6 月 6 日 WWDC 期间提出的,当时我们只有 Xcode 11 和 SwiftUI 的第一个测试版。所以正确回答这个问题需要访问那个版本的 SwiftUI。你可以 download Xcode 11 beta 1 here. (Thank you, xcodereleases.com!) 不过,你正在尝试解压缩存档,因为(我认为)它是用一个已经过期的证书签名的。我使出了黑魔法(单步执行LLDB中的xip
命令,关键时刻修改内存,颠覆证书验证)。您可以在解包之前将系统时间设置回 2019 年 6 月 6 日。
无论如何,这是理解为什么 Text
似乎不符合 View
的秘诀:Xcode,以及 Apple 的文档生成器,故意省略 SDK 中的标识符_
.
因此,如果您想查看类型的完整 public 声明,您不能依赖 Xcode 或文档来向您展示。相反,您必须为模块挖掘 .swiftinterface
文件。对于 SwiftUI,你可以在这里找到它,相对于 Xcode.app
目录:
Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks/SwiftUI.framework/Modules/SwiftUI.swiftmodule/arm64.swiftinterface
在该文件的 Xcode 11 beta 1 版本中,您找不到直接的一致性 Text: View
。相反,您会发现:
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
extension Text : _UnaryView {
public static func _makeView(view: _GraphValue<Text>, inputs: _ViewInputs) -> _ViewOutputs
public typealias Body = Swift.Never
}
你会发现_UnaryView
是View
的一个子协议:
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
public protocol _UnaryView : SwiftUI.View where Self.Body : SwiftUI._UnaryView {
}
因此,在 Xcode 11 beta 1 和相应的 iOS、macOS、tvOS 和 watchOS beta 中,Text
通过其一致性间接符合 View
至 _UnaryView
。由于 _UnaryView
是 SDK 的一部分并且以 _
开头,Xcode 并且 Apple 文档隐藏了该符号。所以通过正常的方法是看不到一致性的。
在后来的某个时候(但我相信,在 Xcode 11.0 测试版期间),Apple 取消了 _UnaryView
协议并使 Text
直接符合 View
.因此,如果您检查 Xcode 11.4(我写这篇文章时的当前版本)中的 SwiftUI .swiftinterface
文件,您会发现:
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
extension Text : SwiftUI.View {
public static func _makeView(view: SwiftUI._GraphValue<SwiftUI.Text>, inputs: SwiftUI._ViewInputs) -> SwiftUI._ViewOutputs
public typealias Body = Swift.Never
}
关于 SwiftUI 中的视图类型,有一件大事让我感到困惑:
它们似乎不符合 View
协议,但不知何故,它们神秘地符合。
以Text
类型为例。定义如下:
public struct Text : Equatable { ... }
我找不到任何 public 扩展符合 View
协议,例如
extension Text: View { ... }
和 official documentation 中的 Relationships 部分简单地指出:
Conforms To: Equatable
仅此而已。
然而,我可以 return 一个 Text
的实例,其中需要一些 View
,例如:
var body: some View {
Text("I'm a View, I swear!")
}
如果 Text
不符合 View
,这是不可能的,并且会抛出编译器错误。
(some View
是一个 不透明的结果类型 这意味着它是一种具有身份的特定类型,但符合 View
.)
这怎么可能?
为 SwiftUI 视图类型指定的 View
协议一致性在哪里(如 Text
、Image
、Circle
、 ...)?
如您所知,有 2 种类型是视图..
- 原始视图:
Text
、Image
、Circle
等 - 容器视图:
List
、HStack
、VStack
等
也就是说,下面是 Text
的扩展,Body 设置为 Never,这意味着它不允许有 body,因为它是一个原始视图,用于结束 body 循环。
因此,(根据我的理解)SwiftUI 在运行时发现原始视图不在容器视图内时将 Text
包装在容器视图内。
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
extension Text {
/// The type of view representing the body of this view.
///
/// When you create a custom view, Swift infers this type from your
/// implementation of the required `body` property.
public typealias Body = Never
}
SwiftUI 视图类型符合 View
协议,否则如您所述,代码将无法编译。我发现其中一些在 SwiftUI public 扩展中可用:
Image
类型有一个直接符合 View
:
extension Image : View {
}
Circle
符合 Shape
,后者本身符合 View
:
public struct Circle : Shape {
...
}
public protocol Shape : Equatable, Animatable, View {
...
}
扩展。
extension Text : View {
/// The type of view representing the body of this view.
///
/// When you create a custom view, Swift infers this type from your
/// implementation of the required `body` property.
public typealias Body = Never
}
这个问题是在 2019 年 6 月 6 日 WWDC 期间提出的,当时我们只有 Xcode 11 和 SwiftUI 的第一个测试版。所以正确回答这个问题需要访问那个版本的 SwiftUI。你可以 download Xcode 11 beta 1 here. (Thank you, xcodereleases.com!) 不过,你正在尝试解压缩存档,因为(我认为)它是用一个已经过期的证书签名的。我使出了黑魔法(单步执行LLDB中的xip
命令,关键时刻修改内存,颠覆证书验证)。您可以在解包之前将系统时间设置回 2019 年 6 月 6 日。
无论如何,这是理解为什么 Text
似乎不符合 View
的秘诀:Xcode,以及 Apple 的文档生成器,故意省略 SDK 中的标识符_
.
因此,如果您想查看类型的完整 public 声明,您不能依赖 Xcode 或文档来向您展示。相反,您必须为模块挖掘 .swiftinterface
文件。对于 SwiftUI,你可以在这里找到它,相对于 Xcode.app
目录:
Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks/SwiftUI.framework/Modules/SwiftUI.swiftmodule/arm64.swiftinterface
在该文件的 Xcode 11 beta 1 版本中,您找不到直接的一致性 Text: View
。相反,您会发现:
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
extension Text : _UnaryView {
public static func _makeView(view: _GraphValue<Text>, inputs: _ViewInputs) -> _ViewOutputs
public typealias Body = Swift.Never
}
你会发现_UnaryView
是View
的一个子协议:
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
public protocol _UnaryView : SwiftUI.View where Self.Body : SwiftUI._UnaryView {
}
因此,在 Xcode 11 beta 1 和相应的 iOS、macOS、tvOS 和 watchOS beta 中,Text
通过其一致性间接符合 View
至 _UnaryView
。由于 _UnaryView
是 SDK 的一部分并且以 _
开头,Xcode 并且 Apple 文档隐藏了该符号。所以通过正常的方法是看不到一致性的。
在后来的某个时候(但我相信,在 Xcode 11.0 测试版期间),Apple 取消了 _UnaryView
协议并使 Text
直接符合 View
.因此,如果您检查 Xcode 11.4(我写这篇文章时的当前版本)中的 SwiftUI .swiftinterface
文件,您会发现:
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
extension Text : SwiftUI.View {
public static func _makeView(view: SwiftUI._GraphValue<SwiftUI.Text>, inputs: SwiftUI._ViewInputs) -> SwiftUI._ViewOutputs
public typealias Body = Swift.Never
}