I'm having a problem displaying all the list elements inside a list when there are multiple sections in the sidebar.
Here is an example code.
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationSplitView {
List {
Section("Test 1") {
List(0...20, id: \.self) { i in
Text("\(i)")
}
}
Section("Test 2") {
List(21...50, id: \.self) { i in
Text("\(i)")
}
}
}
.listStyle(.sidebar)
} detail: {
Text("Details")
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
When I run this code, I get two sections; however the list under them are only showing a single item instead of all.
What am I doing wrong?
You are facing this issue because you are trying to create a nested List inside the section of List. Inside the section of the list, you need to use ForEach to loop through your data instead of creating a nested List.
List {
Section("Test 1") {
ForEach(0...20, id: \.self) { i in
Text("\(i)")
}
}
Section("Test 2") {
ForEach(21...50, id: \.self) { i in
Text("\(i)")
}
}
}
.listStyle(.sidebar)
I am receiving this error message.
I am trying to make a subview that I can reuses to display a row in my app.
For some reason, it is pointing to the index variable that I am using to iterate over my enum in my List to display my data.
Why is this happening? I am not sure how to refer to this variable outside of the subview.
struct DisplayRow: View {
var name: String
var code: String
var value: Double
var counter: Int
var body: some View {
List(0..<counter, id: \.self) {index in
VStack {
HStack {
Text(name)
Text(code)
}
Text("$\(value)")
}
}
}
}
struct ContentView: View {
var body: some View {
List {
Section(header: Text("Wounds")) {
DisplayWoundRow()
}
Section(header: Text("Debride")) {
DisplayRow(name: debride.allCases[index].rawValue, code: debridecode.allCases[index].rawValue, value: debridevalue.allCases[index].rawValue, counter: debride.allCases.count)
}
}
You need ForEach for that, like
Section(header: Text("Debride")) {
ForEach(0..<debride.allCases.count, id: \.self) { index in // << here !!
DisplayRow(name: debride.allCases[index].rawValue, code: debridecode.allCases[index].rawValue, value: debridevalue.allCases[index].rawValue, counter: debride.allCases.count)
}
}
*I don't have all those types and cannot test, so typos or other errors are on you.
A week into learning SwiftUI, this is probably a simple error I'm making but can't figure it out… Trying to separate my views from model etc. However, when I call my view I get the error "Cannot convert value of type 'PuzzleView' to expected argument type 'Puzzle'".
My model is:
struct Puzzle : Codable, Identifiable {
var id: String
var region: String
var score: Int
var wordCount: Int
var pangramCount: Int
var foundPangrams: [String]
var solvedScore: Int
}
class PuzzleData : ObservableObject {
#Published var puzzles: [Puzzle]
init (puzzles: [Puzzle] = []) {
self.puzzles = puzzles
}
}
ContentView (no errors)
struct ContentView: View {
#StateObject var puzzleData : PuzzleData = PuzzleData(puzzles: getJson)
var body: some View {
NavigationView {
List {
ForEach (puzzleData.puzzles) { puzzle in
ListPuzzles(puzzle: puzzle)
}
}
.navigationBarTitle(Text("Puzzles"))
}
}
}
And the problem file with error:
struct PuzzleView: View {
let selectedPuzzle: Puzzle
var body: some View {
VStack {
Group {
Text(selectedPuzzle.id)
.font(.headline)
HStack {
DataRow(selectedPuzzle: Puzzle) //<<<<error here
}
Text(selectedPuzzle.region)
.font(.body)
}
}
}
}
The file it is linking to is:
struct DataRow: View {
var selectedPuzzle: Puzzle
var body: some View {
HStack {
Spacer()
Group {
VStack {
Text("Score")
Text("\(selectedPuzzle.solvedScore)/\\\(selectedPuzzle.score)")
}
VStack {
Text("Words")
Text("\(selectedPuzzle.foundWords.count - 1)/\\\(selectedPuzzle.wordCount)")
}
VStack {
Text("\((selectedPuzzle.pangramCount != 1) ? "Pangrams:" : "Pangram:")")
Text("\(selectedPuzzle.foundPangrams.count - 1)/\\\(selectedPuzzle.pangramCount)")
}
}
}
}
}
Will really appreciate any advise, thanks!
In SwiftUI I want to show the favourite items only and I'm trying to do this with an if statement within the ForEach-element. See the code:
var body: some View {
NavigationView {
List {
Toggle(isOn: $showFavoritesOnly) {
Text("Favorites only")
}
ForEach(self.buildings, id: \.self) { building in
if(!self.showFavoritesOnly || building.favourite) {
Text("Blah")
}
}
}
}
}
However I getting a 'Unable to infer complex closure return type; add explicit type to disambiguate' error.
How can I select an item conditionally in a ForEach element?
Using a filter is a working solution
var body: some View {
NavigationView {
List {
Toggle(isOn: $showFavoritesOnly) {
Text("Favorites only")
}
ForEach(self.buildings.filter({b in self.showFavoritesOnly || b.favourite}), id: \.self) { building in
Text("Blah")
}
}
}
Still, I wonder how could I have fixed it using an if-statement
I have a 2d array with custom types.
I'd like to do something like:
HStack {
ForEach(2dArray) { x in
VStack {
ForEach(self.2dArray[x.index]) { y in
The main issue I have is that I can't figure out how to get x.index.
So I was going to say you should do this to iterate a 2D array:
var data = [[1,2,3],[4,5,6],[7,8,9]]
ForEach(data.identified(by: \.self)) { array in
ForEach(array.identified(by: \.self)) { element in
Text("\(element)")
}
}
but XCode 11 beta is still very buggy with SwiftUI and type inference, so you get a compiler error for doing that, even though it should work. So for now, you'll have to separate everything into functions that the XCode compiler can handle, but with the complex types that SwiftUI uses, it gets ugly very fast. Here is an example:
var data = [[1,2,3],[4,5,6],[7,8,9]]
var body: some View {
doubleForEach(data: data)
}
func doubleForEach(data: [[Int]]) -> ForEach<IdentifierValuePairs<[[Int]], [Int]>,ForEach<IdentifierValuePairs<[Int], Int>, Text>> {
return ForEach(data.identified(by: \.self)) { row in
self.foreach(dataArr: row)
}
}
func foreach(dataArr: [Int]) -> ForEach<IdentifierValuePairs<[Int], Int>, Text> {
return ForEach(dataArr.identified(by: \.self)) { data in
Text("\(data)")
}
}
Which looks like this:
actually the example RPatel99 postet in the earlier response works fine for me:
var data = [[1,2,3],[4,5,6],[7,8,9]]
struct ForTesting : View {
var body: some View {
VStack {
ForEach(data.identified(by: \.self)) { array in
ForEach(array.identified(by: \.self)) { element in
Text("\(element)")
}
}
}
}
}
But was this your problem?
var data = [[1,2,3],[4,5,6],[7,8,9]]
struct ContentView : View {
var body: some View {
VStack {
ForEach(data, id: \.self) { array in
HStack{
ForEach(array, id: \.self) { element in
Text("\(element)")
}
}
}
}
}
}
struct ContentView : View {
var body: some View {
VStack {
ForEach(data.identified(by: \.self)) { array in
HStack{
ForEach(array.identified(by: \.self)) { element in
Text("\(element)")
}
}
}
}
}
}