Issue
This Content is from Stack Overflow. Question asked by Stewart Lynch
I am working with the new Table struct in SwiftUI made available to iOS in iOS 16. I have a simple model
struct City: Identifiable {
var name: String
var country: String
var population: Int
var isCapital: Bool = false
var id: String {
name
}
static var sample: [City] {
[
City(name: "Vancouver", country: "Canada", population: 2632000),
...
...
]
}
}
And a simple View that displays the table and I am trying to sort by columns
struct CountryTableView: View {
@State private var sampleCities = City.sample.sorted(using: KeyPathComparator(.name))
@State private var sortOrder = [KeyPathComparator(City.name)]
var body: some View {
Table(sampleCities, sortOrder: $sortOrder) {
TableColumn("Name", value: .name)
TableColumn("Capital") { city in
HStack {
Spacer()
Text(city.isCapital ? "🌟" : "")
Spacer()
}
}
.width(60)
TableColumn("Country", value: .country)
TableColumn("Population", value: .population) { city in
Text("(city.population)")
}
}
.onChange(of: sortOrder) { newOrder in
sampleCities.sort(using: newOrder)
}
}
}
The above works well. I can sort on both of the String and Int KeyPaths. However,if I try to add a value for the Boolean keypath
TableColumn("Capital", value: .isCapital) { city in
I get this error
Referencing initializer 'init(_:value:content:)' on 'TableColumn' requires the types 'KeyPathComparator<City>' and 'SortDescriptor<City>' be equivalent
and this one
Referencing initializer 'init(_:value:content:)' on 'TableColumn' requires that 'City' inherit from 'NSObject'
This makes no sense to me as I can sort on String and Int KeyPaths but not the Boolean one.
Can anyone shed some light?
Solution
The docs (https://developer.apple.com/documentation/swiftui/tablecolumn/) do not mention using Bool
for value
in columns (lots of Int), but
you could try this approach, using a computed property, works for me:
struct City: Identifiable {
var name: String
var country: String
var population: Int
var isCapital: Bool = false
var id: String {
name
}
var isCapitalString: String { // <-- here
isCapital ? "🌟" : ""
}
static var sample: [City] {
[
City(name: "Vancouver", country: "Canada", population: 2632000),
City(name: "Tokyo", country: "Japan", population: 1632000, isCapital: true),
City(name: "Sydney", country: "Australia", population: 32000)
]
}
}
struct ContentView: View {
@State private var sampleCities = City.sample.sorted(using: KeyPathComparator(\.name))
@State private var sortOrder = [KeyPathComparator(\City.name)]
var body: some View {
Table(sampleCities, sortOrder: $sortOrder) {
TableColumn("Name", value: \.name)
TableColumn("Capital", value: \.isCapitalString) { city in // <-- here
Text(city.isCapitalString)
}.width(60)
TableColumn("Country", value: \.country)
TableColumn("Population", value: \.population) { city in
Text("\(city.population)")
}
}
.onChange(of: sortOrder) { newOrder in
sampleCities.sort(using: newOrder)
}
}
}
This Question was asked in StackOverflow by Stewart Lynch and Answered by workingdog support Ukraine It is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.