Если я понимаю вашу конечную цель, это чтобы каждая строка была обведена пунктирной линией, без отступов между ними, например:

В этом случае, IMO, вы должны поместить линии в фоновом режиме. Например:
ScrollView {
VStack(alignment: .leading) {
ForEach(self.elements, id: \.self) { element in
HStack {
Text("\(element.index+1)")
.font(.system(.caption, design: .rounded))
.frame(width: 32, alignment: .trailing)
Text(element.element)
.font(.system(.caption, design: .monospaced))
Spacer()
}
.background(
ZStack(alignment: .top) {
Color.green
GeometryReader { geometry in
Path { path in
path.move(to: .zero)
path.addLine(to: CGPoint(x: geometry.size.width, y: 0))
}
.strokedPath(StrokeStyle(lineWidth: 1, dash: [1,2]))
.foregroundColor(Color.red)
}
}
)
}
}
}
Ключевым моментом является то, что ScrollView не является вертикальным контейнером с накоплением. Он просто берет свое содержимое и делает его прокручиваемым. Его содержимое в вашем коде является ForEach, который генерирует представления; на самом деле он не намерен их выкладывать. Поэтому, когда вы объединяете ScrollView с ForEach, на самом деле ничто не отвечает за размещение представлений так, как вы хотите. Чтобы расположить представления вертикально, вам нужен VStack.
Вы также можете применить это к своей структуре, но добавив еще один VStack, и получите те же результаты:
ScrollView {
VStack(spacing: 0) { // <---
ForEach(self.elements, id: \.self) { element in
VStack(alignment: .leading, spacing: 0) {
GeometryReader { geometry in
Path { path in
path.move(to: .init(x: 0, y: 0))
path.addLine(to: .init(x: geometry.size.width, y: 0))
}
.strokedPath(.init(lineWidth: 1, dash: [1,2]))
}
.foregroundColor(.red)
.frame(height: 1)
HStack {
Text("\(element.index+1)")
.font(.system(.caption, design: .rounded))
.frame(width: 32, alignment: .trailing)
Text(element.element)
.font(.system(.caption, design: .monospaced))
.frame(maxWidth:nil)
Spacer()
}
}
.background(Color.green) // <-- Moved
}
}
}