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 |1 Answer
Reset to default 1Without an explicit tag
, ForEach
on a collection of Identifiable
elements automatically tag
s each view with the elements' id
s. 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 tag
s 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 Employee
s, and they use a Set<Employee.ID>
to record the list selection. This is because the automatically-added tag
s 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
Employee.ID
) and not the type itself for the selection property. – Joakim Danielson Commented Mar 26 at 12:53