TL; DR:一个人如何修改ForEach
结构中的内容?
以下是一个自包含的游乐场,其中以简单的frame()
方法对body
的调用是可以的,但是如果包裹在ZStack/ForEach
循环中则是语法错误。
import UIKit
import SwiftUI
struct Item: Identifiable {
var id = UUID()
var name: String
init(_ name:String) { self.name = name }
}
let items = [
Item("a"), Item("b"), Item("c")
]
struct ContentView: View {
var body: some View {
return Image("imageName")
.resizable()
.frame(width:0, height:0) // This compiles.
}
var body2: some View {
ZStack {
ForEach(items) { item -> Image in // Return type required...
let i = item // ...because of this line.
return Image(i.name)
.resizable() // Parens required.
.frame(width: 0, height: 0) // Compile error.
}
}
}
}
注意第let i = item
行。它代表我的应用中执行一些计算的代码。 ForEach
闭包不是单个表达式的事实导致编译器抱怨
无法推断复杂的闭包返回类型;添加显式类型以消除歧义。
这促使我添加了返回类型。但是那带来了这个问题的主题,即编译器错误:
无法将“某些视图”类型的返回表达式转换为“图像”类型
似乎frame()
调用的返回值不是Image
,而是ModifiedContent<SwiftUI.Image, SwiftUI._FrameLayout>
。
我已经发现(感谢评论者!)我可以通过(以某种方式)将ForEach
闭包简化为单个表达式来解决这个问题,这使返回类型变得难以理解,然后可以将其删除。这是我唯一的资源吗?
答案 0 :(得分:1)
据我所知,这可能只是Swift的一种局限性,类似于此类型推断问题:Why can't the Swift compiler infer this closure's type?
我的解决方法是向Item
结构添加功能。现在ForEach
实例提供了item
闭包内部所需的每个计算,它们直接插入Image
初始化程序,如下所示:
var body3: some View {
ZStack {
ForEach(items) { item in // No return type specified.
// let (width, height) = ... // Remove pre-calculations that
// confused the compiler.
Image(item.name)
.resizable()
.frame(
width : item.width, // All needed data are
height: item.height // provided in closure param.
)
}
}
}
}
尽管我更喜欢在电话会议之前进行一些精心挑选的分配的明确性,但我认为这是更惯用的功能。 (如果分配的计算没有副作用,则本质上是SSA风格,应通过FP气味测试。)
所以我称其为“答案”,甚至是“解决方案”,尽管我仍然会抱怨无用的错误消息。但这是一个已知问题,比我聪明的人已经在解决这个问题。
答案 1 :(得分:0)
现在,我必须考虑一下。但是要消除第一个错误,需要使 Item 与可识别的内容保持一致。
struct Item: Identifiable {
var id = UUID()
var name: String
var size: CGSize = .zero
}
我还必须编写一个自定义修饰符,以使用该项目创建框架。我们可能希望使用CGRect进行网格物体的创建,并通过某种方式弄乱图像的原点。
extension View {
func frame(with size: CGSize) -> some View {
frame(width: size.width, height: size.height)
}
}
然后您的身体将看起来像这样。
var body: some View {
ZStack {
ForEach(items) { item in
Image(item.name).resizable().frame(with: item.size)
}
}
}
答案 2 :(得分:0)
这是这里
setproctitle(3)
您明确指定闭包返回ForEach(items) { item -> Image in
,但是Image
返回frame
,因此键入不匹配和编译器错误。
按如下所述使用,它将起作用
some View