TL;DR: How does one modify content inside a ForEach
structure?
The following is a self-contained Playground, in which the call to frame()
is OK in a plain body
method, but is a syntax error when wrapped in a ZStack/ForEach
loop.
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.
}
}
}
}
Note the line let i = item
. It is standing in for code in my app that performs some calculations. The fact that the ForEach
closure is not a single expression caused the compiler to complain
Unable to infer complex closure return type; add explicit type to disambiguate.
which motivated my adding the return type. But that brings about the topic of this question, the compiler error:
Cannot convert return expression of type 'some View' to return type 'Image'
It appears that the return value of the frame()
call is not an Image
but a ModifiedContent<SwiftUI.Image, SwiftUI._FrameLayout>
.
I have discovered (thanks to commenters!) I can get around this by (somehow) reducing the ForEach
closure to a single expression, which renders inferrable the return type, which I can then remove. Is this my only recourse?