SwiftUI中ForEach结构体的最后一个参数的函数类型是什么



上下文:我正在学习https://developer.apple.com/tutorials/swiftui/了解Swift和iOS。

在学习Swift中的闭包表示法时,我想写一个我遇到的闭包的扩展版本。

ForEach(filteredLandmarks) {
landmark in
NavigationLink(destination: LandmarkDetail(landmark: landmark)) {
LandmarkRow(landmark: landmark)
}
}

第一段代码非常有效。

根据我对尾随闭包的理解,作为ForEach结构的最后一个参数所需的函数类型意味着由闭包定义的函数类型,因此我们不需要显式地说由闭包定义函数的类型,并且只隐式地引用它的唯一参数landmark。但是,如果我想明确定义它,它的类型是什么?

以下是我的尝试,它在Xcode 中产生错误

协议类型"View"的值不能符合"View";只有结构/枚举/类类型才能符合协议

ForEach(filteredLandmarks) {
(landmark: Landmark) -> View in
NavigationLink(destination: LandmarkDetail(landmark: landmark)) {
LandmarkRow(landmark: landmark)
}
}

我知道landmark有一种类型的Landmark,因为去掉-> View效果很好。所以说真的,我只需要知道返回类型是什么?

您正在调用此初始化程序:

init(_ data: Data, content: @escaping (Data.Element) -> Content)

(当Data符合RandomAccessCollectionIDData.Element.IDContent符合ViewData.Element符合Identifiable时可用。(

正如您所看到的,闭包应该返回Content。什么是Content

ForEach实际上是一个泛型类型,DataContent实际上是ForEach:的泛型类型参数

struct ForEach<Data, ID, Content> 
where Data : RandomAccessCollection, ID : Hashable

这意味着可以决定什么是Content

使用-> View不起作用,因为要使该初始化程序可用,Content必须符合ViewView不符合View,所以您不能这样做。

在您的代码中,您将返回一个NavigationLink,这实际上是ForEachContent类型。你应该做:

(landmark: Landmark) -> NavigationLink in

然而,问题是,NavigationLink也是通用的!您必须指定其通用参数!

destination参数的类型是第二个泛型参数,在尾部闭包中返回的视图是它的第一个泛型参数。假设LandmarkDetailLandmarkRow不是通用的,您需要执行以下操作:

(landmark: Landmark) -> NavigationLink<LandmarkRow, LandmarkDetail> in

请注意,在编写SwiftUI时,大多数时候都无法分析闭包返回的类型。假设你做到了:

ForEach(filteredLandmarks) {
landmark in
NavigationLink(destination: LandmarkDetail(landmark: landmark)) {
LandmarkRow(landmark: landmark).padding()
}
}

相反,我们将无法知道NavigationLink的第一个泛型参数的确切类型,因为padding返回some View的不透明类型。请注意,您也可以在关闭返回类型中这样做:

(landmark: Landmark) -> some View in

在发布后不久就发现了这一点,很有趣。

这个问题有答案,因为闭包返回了一些东西,所以我们只需要知道返回的是什么类型。

有问题的闭包返回NavigationLink

NavigationLink<标签,目的地>其中标签:查看,目的地:查看

NavigationLink的Destination参数被明确地标识为LandmarkDetail对象。Label参数由尾部闭包定义。答案是这样的。

ForEach(filteredLandmarks) {
(landmark: Landmark) -> NavigationLink<LandmarkRow, LandmarkDetail> in
NavigationLink(destination: LandmarkDetail(landmark: landmark)) {
LandmarkRow(landmark: landmark)
}
}

相关内容

  • 没有找到相关文章

最新更新