List with 2 cells side by side

From the Landmarks sample project, I tried a variation, to get two cells side by side in the List.

This is the original with on cell per row as in the tutorial:
Code Block
struct LandmarkList: View {
var body: some View {
List(landmarks) { landmark in
LandmarkRow(landmark: landmark)
}
}
}

Surprisingly, the following variation works well to display 2 cells side by side:

Code Block
struct LandmarkList: View {
var body: some View {
List (0 ..< (landmarks.count+1)/2) { item in
LandmarkRow(landmark: landmarks[2*item])
if 2*item + 1 < landmarks.count {
LandmarkRow(landmark: landmarks[(2*item)+1])
}
}
}
}

I thus tried to go on and add navigationLinks…
It works when adding a navigation link to the first cell only
Code Block
struct LandmarkList: View {
var body: some View {
NavigationView {
List (0 ..< (landmarks.count+1)/2) { item in
NavigationLink(destination: LandmarkDetail()) {
LandmarkRow(landmark: landmarks[2*item])
}
if 2*item + 1 < landmarks.count {
LandmarkRow(landmark: landmarks[(2*item)+1])
}
}
.navigationTitle("Landmarks")
}
}
}

But adding NavigationLink to the second makes it fail:

Code Block
struct LandmarkList: View {
var body: some View {
NavigationView {
List (0 ..< (landmarks.count+1)/2) { item in
NavigationLink(destination: LandmarkDetail()) {
LandmarkRow(landmark: landmarks[2*item])
}
if 2*item + 1 < landmarks.count {
NavigationLink(destination: LandmarkDetail()) {
LandmarkRow(landmark: landmarks[(2*item)+1])
}
}
}
.navigationTitle("Landmarks")
}
}
}


The error is on line 3:

The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions

Is it a normal List behaviour ?
Or did I miss something ?
Which expression could I break ?


Answered by Claude31 in 654922022
Thanks for the hint.

id: \.self was missing here.
In addition, I had to specify the landmark.

This does "work", at least compile and run

Code Block
List (0 ..< (landmarks.count+1)/2, id: \.self) { item in
NavigationLink(destination: LandmarkDetail(landmark: landmarks[2*item])) {
LandmarkRow(landmark: landmarks[2*item])
}
if 2*item + 1 < landmarks.count { NavigationLink(destination: LandmarkDetail(landmark: landmarks[(2*item)+1])) {
LandmarkRow(landmark: landmarks[(2*item)+1])
}
}
}


However, when I activate a link, I get the behaviour you described:
  • links to the first item in row

Then if I return back to List
  • links to second item automatically.

In addition, I get the error log:
SwiftUI encountered an issue when pushing aNavigationLink. Please file a bug.

What I did: Dec 31, 2020 at 9:11 PM – FB8958299
The error on line 3 is a bug in Swift where it can't determine the type of an expression in reasonable time. It's quite an annoying one, but there are ways to mitigate it (search for the error on your favorite search engine).

Other than that, your code is syntactically, but may not play well on screen when having two navigation views positioned horizontally. Take this code for example:
Code Block swift
struct ContentView: View {
    var body: some View {
        NavigationView {
            List(1..<11, id: \.self) { num in
                NavigationLink("Number: \(num)", destination: Text("Destination Number: \(num)"))
                NavigationLink("Integer: \(num)", destination: Text("Destination Integer: \(num)"))
            }
        }
    }
}

This creates a list where the two navigation views are positioned horizontally (by default, list rows are horizontal instead of vertical). However, the two arrows indicating a new view is ahead are visible, and clicking on either one will present the second one right after clicking the back button.

Wrapping the row content in a ScrollView solves both of those issues, but it's not ideal, because on a platform like macOS, it treats it like its own individual scroll view, which makes scrolling down weird. But on iOS, it looks and functions correctly. The same for iPadOS when there's no third split view.
Accepted Answer
Thanks for the hint.

id: \.self was missing here.
In addition, I had to specify the landmark.

This does "work", at least compile and run

Code Block
List (0 ..< (landmarks.count+1)/2, id: \.self) { item in
NavigationLink(destination: LandmarkDetail(landmark: landmarks[2*item])) {
LandmarkRow(landmark: landmarks[2*item])
}
if 2*item + 1 < landmarks.count { NavigationLink(destination: LandmarkDetail(landmark: landmarks[(2*item)+1])) {
LandmarkRow(landmark: landmarks[(2*item)+1])
}
}
}


However, when I activate a link, I get the behaviour you described:
  • links to the first item in row

Then if I return back to List
  • links to second item automatically.

In addition, I get the error log:
SwiftUI encountered an issue when pushing aNavigationLink. Please file a bug.

What I did: Dec 31, 2020 at 9:11 PM – FB8958299
List with 2 cells side by side
 
 
Q