All examples regarding SwiftUI Tables and sorting work fine, but they also have all the data available immediately.
If I load the data in .task, sorting only works on the first column.
Test data:
struct Customer: Identifiable {
let id = UUID()
let name: String
let email: String
let creationDate: Date
}
func parseDate(from text: String) -> Date {
let formatter = DateFormatter()
formatter.dateFormat = "dd/MM/yyyy"
return formatter.date(from: text) ?? Date()
}
func getTestData() -> [Customer] {
return [
Customer(name: "John Smith",
email: "john.smith@example.com",
creationDate: parseDate(from: "04/11/2015")),
Customer(name: "Jane Doe",
email: "jane.doe@example.com",
creationDate: parseDate(from: "29/04/2009")),
Customer(name: "Bob Johnson",
email: "bob.johnson@example.com",
creationDate: parseDate(from: "01/08/2010"))]
}
And here the view:
table 1 populates the array in the initializer
table 2 loads the content in .task, initially it is empty
table 3 loads the content in .task, initially it contains one dummy object
struct SortableTable: View {
@State var customers1 = getTestData()
@State var customers2: [Customer] = []
@State var customers3: [Customer] = [Customer(name: "", email: "", creationDate: Date())]
@State private var sortOrder1 = [KeyPathComparator(\Customer.name)]
@State private var sortOrder2 = [KeyPathComparator(\Customer.name)]
@State private var sortOrder3 = [KeyPathComparator(\Customer.name)]
var body: some View {
Table(customers1, sortOrder: $sortOrder1) {
TableColumn("name", value: \.name)
TableColumn("email", value: \.email)
TableColumn("joined at", value: \.creationDate) { customer in
Text(customer.creationDate, style: .date)
}
}
.frame(height: 200)
.onChange(of: sortOrder1) { oldOrder, newOrder in
customers1.sort(using: newOrder)
}
Table(customers2, sortOrder: $sortOrder2) {
TableColumn("name", value: \.name)
TableColumn("email", value: \.email)
TableColumn("joined at", value: \.creationDate) { customer in
Text(customer.creationDate, style: .date)
}
}
.frame(height: 200)
.onChange(of: sortOrder2) { oldOrder, newOrder in
customers2.sort(using: newOrder)
}
.task {
customers2 = getTestData()
}
Table(customers3, sortOrder: $sortOrder3) {
TableColumn("name", value: \.name)
TableColumn("email", value: \.email)
TableColumn("joined at", value: \.creationDate) { customer in
Text(customer.creationDate, style: .date)
}
}
.frame(height: 200)
.onChange(of: sortOrder3) { oldOrder, newOrder in
customers3.sort(using: newOrder)
}
.task {
customers3 = getTestData()
}
Spacer()
}
}
The result is that table 1 and table 3 can be sorted by all columns, while table 2 can only be sorted (for whatever reason) be the first column:
HIH and let me know, if I misunderstood something.
Post
Replies
Boosts
Views
Activity
I have a ProgressView in a Form, that's being toggled on and off. The first time it shows correctly, subsequently it does not. Outside of a Form it works correctly.
Here's the sample code:
struct BugWithProgress: View {
@State var toggle: Bool = false
var body: some View {
Text("in form:").font(.title)
Form {
Toggle(isOn: $toggle, label: {
Text("isOn: \(toggle)")
})
if toggle {
HStack {
ProgressView()
Spacer()
ProgressView("Working...")
Spacer()
Text("Working...")
}
}
}
.frame(height: 200)
Text("outside form:").font(.title)
if toggle {
HStack {
ProgressView()
Spacer()
ProgressView("Working...")
Spacer()
Text("Working...")
}
}
}
}
#Preview {
BugWithProgress()
}
If I toggle it on once, it looks as expected.
Here's what it looks like after I toggled it on twice or more:
As you can see, the spinning parts are missing within the Form.
Any suggestions or workarounds?
PS: Is this the correct place for SwiftUI bug reports?
I'm trying to display a picker with .pickerStyle(.segmented), including text and an image, but there seems to be a bug.
Take the following pickers (not segmented):
struct BugInPicker: View {
@State var sel = -1
let trashes = ["trash", "trash.fill", "trash.slash", "trash.slash.fill"]
var body: some View {
VStack {
Picker(selection: $sel, label: Text("Trash type")) {
ForEach(0 ..< trashes.count) { (i) in
Text(self.trashes[i])
}
}
Picker(selection: $sel, label: Text("Trash type")) {
ForEach(0 ..< trashes.count) { (i) in
Label(self.trashes[i], systemImage: self.trashes[i])
}
}
Picker(selection: $sel, label: Text("Trash type")) {
ForEach(0 ..< trashes.count) { (i) in
HStack {
Image(systemName: self.trashes[i])
Text(self.trashes[i])
}.tag(i)
}
}
}
}
}
The first one displays simlple text, the second one includes an image via a label, the third one has image and text manually. And they work fine.
As soon as I add .pickerStyle(.segmented) to these pickers,
the first one displays text, as it should.
The second one also displays text only, the image is not displayed!
The third one now has not 4 but 8 entries, each image and each text get their own picker entry.
Here with and without the style: