ios - SwiftUI NavigationSplitView: Confused due to an official example by Apple - Stack Overflow

I'm tinkering with SwiftUI-NavigationSplitView. I started with this example from the official Deve

I'm tinkering with SwiftUI-NavigationSplitView. I started with this example from the official Developer-documentation.

Overview

The UI, I have made is very similar:

import SwiftUI

struct ContentView: View {
    @State var articles = [Article]()
    @State var selectedArticle: Article?
    
    var body: some View {
        NavigationSplitView {
            List(selection: $selectedArticle) {
                ForEach(articles) { article in
                    // With attached .tag-modifier it works fine.
                    Text(article.name) // .tag(article)
                }
            }
        } detail: {
            VStack(alignment: .leading) {
                Text(selectedArticle?.name ?? "")
                    .font(.title2)
                    .bold()
                Text(selectedArticle?.desc ?? "")
                Spacer()
            }.padding()
        }
        .onChange(of: selectedArticle, {
            print(selectedArticle?.id)
            print(" ------------- ")
        })
        .onAppear() {
            for i in 1...6 {
                let article = Article(
                    name: "Name_\(i)",
                    desc: "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor.\nIn enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus."
                )
                articles.append(article)
            }
        }
    }
}

#Preview {
    ContentView()
}

The Article-struct, I'm using:

struct Article: Identifiable, Hashable {
    let id = UUID()
    var name: String
    var desc: String
}

Previously it hadn't the .tag-modifier attached to the list-items.

It didn't work. The selectedArticle-variable never changed.

Finally I found a forum-post, where I saw the usage of .tag. That remind me, how it could work.

But I still don't understand the example of Apple.

How is it possible, that the Apple-example works? In case it really works. Can someone give some insights?

Has it to do with the usage of IDs?

I'm tinkering with SwiftUI-NavigationSplitView. I started with this example from the official Developer-documentation.

Overview

The UI, I have made is very similar:

import SwiftUI

struct ContentView: View {
    @State var articles = [Article]()
    @State var selectedArticle: Article?
    
    var body: some View {
        NavigationSplitView {
            List(selection: $selectedArticle) {
                ForEach(articles) { article in
                    // With attached .tag-modifier it works fine.
                    Text(article.name) // .tag(article)
                }
            }
        } detail: {
            VStack(alignment: .leading) {
                Text(selectedArticle?.name ?? "")
                    .font(.title2)
                    .bold()
                Text(selectedArticle?.desc ?? "")
                Spacer()
            }.padding()
        }
        .onChange(of: selectedArticle, {
            print(selectedArticle?.id)
            print(" ------------- ")
        })
        .onAppear() {
            for i in 1...6 {
                let article = Article(
                    name: "Name_\(i)",
                    desc: "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor.\nIn enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus."
                )
                articles.append(article)
            }
        }
    }
}

#Preview {
    ContentView()
}

The Article-struct, I'm using:

struct Article: Identifiable, Hashable {
    let id = UUID()
    var name: String
    var desc: String
}

Previously it hadn't the .tag-modifier attached to the list-items.

It didn't work. The selectedArticle-variable never changed.

Finally I found a forum-post, where I saw the usage of .tag. That remind me, how it could work.

But I still don't understand the example of Apple.

How is it possible, that the Apple-example works? In case it really works. Can someone give some insights?

Has it to do with the usage of IDs?

Share Improve this question edited Mar 26 at 13:26 cluster1 asked Mar 26 at 12:19 cluster1cluster1 5,8167 gold badges38 silver badges59 bronze badges 4
  • You haven't told us what Article is but notice that Apple is using the identifier of the type (Employee.ID) and not the type itself for the selection property. – Joakim Danielson Commented Mar 26 at 12:53
  • @JoakimDanielson I've have my question completed. – cluster1 Commented Mar 26 at 13:27
  • 1 Did you try to use Article.ID instead which you can do since your type conforms to Identifiable? – Joakim Danielson Commented Mar 26 at 13:42
  • 1 ID is the way to go – malhal Commented Mar 26 at 18:58
Add a comment  | 

1 Answer 1

Reset to default 1

Without an explicit tag, ForEach on a collection of Identifiable elements automatically tags each view with the elements' ids. It is as if you have wrote:

ForEach(articles) { article in
    Text(article.name).tag(article.id)
}

The code in Apple's documentation uses the List initialiser that takes a collection directly, which implicitly adds tags the same way.

As you may know, the selection of the List contains the tags of the list rows that are selected.

In the documentation's code, the list is displaying some Employees, and they use a Set<Employee.ID> to record the list selection. This is because the automatically-added tags are of type Employee.ID.

@State private var employeeIds: Set<Employee.ID> = []
//                                  ^^^^^^^^^^^

var body: some View {
    NavigationSplitView {
        List(model.employees, selection: $employeeIds) { employee in
            Text(employee.name)//.tag(employee.id)
        }
    } detail: {
        EmployeeDetails(for: employeeIds)
    }
}

In your code however, you have used a Article? to record the list selection.

@State var selectedArticle: Article?

This does not match the tags of your list rows. The list rows' automatically-added tags are of type Article.ID, aka UUID. This is why selectedArticle never changes - you did not select anything that has a tag of type Article.

If you change selectedArticle to be of type Article.ID?, then it will work with the automatically-added tags.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744145769a4560413.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信