Post

Replies

Boosts

Views

Activity

SwiftUI: Performance problems List of TextField
I'm having issues with the scrolling performance in my app. I use CloudKit to store a list of Items. I access these Items with @FetchRequest var items : FetchedResults<Item> I created a List with a ForEach inside to iterate over the items and pass them to a ChecklistItemView. The ChecklistItemView accesses the Item as an @ObservedObject. This all works fine and I am able to edit the items with the Textfields but the performance when scrolling is very bad. On my iPhone 12 mini I get light stuttering and on my older iPad pro it gets very bad. Interestingly everything is smooth when the item is just displayed with Text(). My guess is that the Textfields update the item during binding when the TextField appears on screen. This is updating the whole list of items then triggering a redraw of all Textfields, resulting in a stuttering scrolling experience, because the view is redrawn again and again. It does not get worse with longer list. It is enough to fill the screen and then some more to be able to scroll. Because I'm still very new to swiftUI I'm not sure how to fix this problem. Maybe it is possible to load each item in the ChecklistItemView to not update the other ones but I'm unsure on how to do that properly. Thank you for your help in advance! The list is setup like this: ... @FetchRequest var items : FetchedResults<Item> init(selectedchecklist: Checklist) {         self.checklist = selectedchecklist         self._items = FetchRequest(entity: Item.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \Item.position, ascending: true)], predicate: NSPredicate(format: "checklist.id == %@", selectedchecklist.id! as CVarArg)) } var body: some View {     VStack(spacing: 0) {         if(!self.items.isEmpty) {             List {                 ForEach(self.items, id: \.id) { item in                     ChecklistItemView(item: item, isEditingDisabled: self.$addItemMode)                 }                 .onMove(perform: move)                 .onDelete(perform: deleteItems)             }             .listStyle(.plain)         }         if(self.items.isEmpty) { ...         } } } File ChecklistItemView: import SwiftUI struct ChecklistItemView: View {     @Environment(\.managedObjectContext) private var viewContext     @ObservedObject var item: Item     @FocusState private var isTextfieldFocused: Bool     @Binding var isEditingDisabled: Bool     var body: some View {         HStack {             if(self.isEditingDisabled) {                 Text(self.item.wrappedDesc)                     .padding(.bottom, 2)             } else {                 TextField("", text: self.$item.wrappedDesc, axis: .vertical)                 .onChange(of: self.item.wrappedDesc, perform: { newValue in                     saveItem()                 })                 .disableAutocorrection(true)                 .focused(self.$isTextfieldFocused)             }             Spacer()             CheckboxView(isChecked: self.$item.completed)         }         .toolbar{             if(self.isTextfieldFocused) {                 ToolbarItemGroup(placement: .keyboard) {                     Spacer()                     Button("_done") {                         withAnimation{                             self.isTextfieldFocused = false                         }                         saveItem()                     }                 }             }         }         .contentShape(Rectangle())         .onTapGesture {             if (!self.isEditingDisabled) {                 self.isTextfieldFocused = true             }         }     }       private func saveItem() {        ...     } }
2
0
1.4k
Feb ’23
NSItemProvider.loadObject in DropDelegate->dropEntered(info: DropInfo) not executed on iOS
I have a Problem implementing drag and drop in my App. My code is the following: swift struct MyDropDelegate: DropDelegate { ... func performDrop(info: DropInfo) - Bool {         let items = info.itemProviders(for: ["public.url"])         for item in items {             _ = item.loadObject(ofClass: URL.self) { data, error in                 if let url = data { ...                     } } } return true     }     func dropEntered(info: DropInfo) {         let items = info.itemProviders(for: ["public.url"])         for item in items {             _ = item.loadObject(ofClass: URL.self) { data, error in                 if let url = data { ...                     } } }     } ... } Everything is working fine on macOS. But if I run the same code on iOS or iPadOS it does not work. Everything inside the .loadObject() {...} method is not executed. If I print something to console in this method, it will not be printed. This also works fine on macOS. The weird part is, that the exact same code is executed fine in the performDrop method. Am I missing something important, or is this a bug? Because it all works fine when executed on macOS. I hope someone can help me.
0
0
743
Mar ’21