SwiftUI 中 ForEach 结构的最后一个参数的函数类型是啥?
Posted
技术标签:
【中文标题】SwiftUI 中 ForEach 结构的最后一个参数的函数类型是啥?【英文标题】:What is the function type of the last parameter of the ForEach struct from SwiftUI?SwiftUI 中 ForEach 结构的最后一个参数的函数类型是什么? 【发布时间】:2021-04-26 06:05:23 【问题描述】:上下文:我正在关注https://developer.apple.com/tutorials/swiftui/ 上的教程来了解 Swift 和 ios。
在学习 Swift 中的闭包表示法时,我想编写我遇到的闭包的扩展版本。
ForEach(filteredLandmarks)
landmark in
NavigationLink(destination: LandmarkDetail(landmark: landmark))
LandmarkRow(landmark: landmark)
第一个代码 sn-p 效果很好。
根据我对尾随闭包的理解,ForEach
结构的最后一个参数所需的函数类型暗示了闭包定义的函数的类型,因此我们不需要明确说明闭包定义的函数的类型,并且仅隐式引用它的唯一参数landmark
。但是如果我想显式定义它的类型是什么?
以下是我的尝试,它在 Xcode 中产生错误
协议类型'View'的值不能符合'View';只有结构/枚举/类类型可以符合协议
ForEach(filteredLandmarks)
(landmark: Landmark) -> View in
NavigationLink(destination: LandmarkDetail(landmark: landmark))
LandmarkRow(landmark: landmark)
我知道landmark
的类型是Landmark
,因为删除-> View
效果很好。所以真的,我只需要知道返回类型是什么?
【问题讨论】:
【参考方案1】:你打电话给this initialiser:
init(_ data: Data, content: @escaping (Data.Element) -> Content)
(当Data
符合RandomAccessCollection
、ID
为Data.Element.ID
、Content
符合View
、Data.Element
符合Identifiable
时可用。)
如您所见,闭包应该返回Content
。什么是Content
?
ForEach
其实是泛型类型,Data
和Content
其实是ForEach
的泛型类型参数:
struct ForEach<Data, ID, Content>
where Data : RandomAccessCollection, ID : Hashable
这意味着你可以决定Content
是什么。
使用-> View
不起作用,因为要使该初始化程序可用,Content
必须符合View
。 View
does not conform to View
,所以你不能这样做。
在您的代码中,您返回一个NavigationLink
,这确实是ForEach
的Content
类型。你应该这样做:
(landmark: Landmark) -> NavigationLink in
然而,问题是,NavigationLink
也是通用的!你必须指定它的泛型参数!
destination
参数的类型是第二个泛型参数,你在尾随闭包中返回的视图是它的第一个泛型参数。假设 LandmarkDetail
和 LandmarkRow
不是通用的,您需要这样做:
(landmark: Landmark) -> NavigationLink<LandmarkRow, LandmarkDetail> in
请注意,在编写 SwiftUI 时,大多数情况下无法分析闭包返回什么类型。假设你这样做了:
ForEach(filteredLandmarks)
landmark in
NavigationLink(destination: LandmarkDetail(landmark: landmark))
LandmarkRow(landmark: landmark).padding()
相反,我们将无法知道NavigationLink
的第一个泛型参数的确切类型,因为padding
返回opaque type 的some View
。请注意,您也可以在闭包返回类型中执行此操作:
(landmark: Landmark) -> some View in
【讨论】:
太棒了!我很难找到我正在搜索的任何东西的 init 文档,因为它出现在我没想到的示例之后。我不会说“不可能对闭包返回的类型进行这种分析”。返回的不透明类型的示例非常有用且信息丰富,但这正是返回的类型,因此这种分析绝对是可能的,只需使用不透明类型,而不是常规类型,如您所说。也许说这样对闭包返回什么类型的分析比较模棱两可。【参考方案2】:发布后不久就想通了,这很有趣。
问题有答案,因为闭包是返回一些东西,所以我们只需要知道返回的是什么类型。
有问题的关闭返回一个NavigationLink
NavigationLink
来自docs。
NavigationLink
的 Destination 参数被明确标识为 LandmarkDetail
对象。 Label 参数由尾随闭包定义。这是答案。
ForEach(filteredLandmarks)
(landmark: Landmark) -> NavigationLink<LandmarkRow, LandmarkDetail> in
NavigationLink(destination: LandmarkDetail(landmark: landmark))
LandmarkRow(landmark: landmark)
【讨论】:
以上是关于SwiftUI 中 ForEach 结构的最后一个参数的函数类型是啥?的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI:如何使用 ForEach 循环使用各种代码的各种结构?