Post

Replies

Boosts

Views

Activity

Reply to SwiftUI ScrollViewProxy.scrollTo(_:anchor:) always crash in iOS 16 beta 7: NSInternalInconsistencyException
I ran into this crash with ios 16 as well. Here is what I eventually came up with that works: use the SwiftUI Introspection library to get the UIScrollView interact with the UIScrollView directly This code works on ios 15 and ios 16. There is likely tweaks to be done to make it feel right. I had to tweak the timing of asyncAfter() in my code where the keyboard is animated. Using .now() + 0.25 seems to do the trick. So far this has been working and has been stable. struct ScrollListOnChangeIos16: View { @State private var items: [String] init() { _items = State(initialValue: Array(0...25).map { "Placeholder \($0)" } ) } // The .introspectX view modifiers will populate scroller // they are actually UITableView or UICollectionView which both decend from UIScrollView // https://github.com/siteline/SwiftUI-Introspect/releases/tag/0.1.4 @State private var scroller: UIScrollView? func scrollToTop() { scroller?.setContentOffset(CGPoint(x: 0, y: 0), animated: true) } func scrollToBottom() { // Making this async seems to make scroll more consistent to happen after // items has been updated. *shrug?* DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) { guard let scroller = self.scroller else { return } let yOffset = scroller.contentSize.height - scroller.frame.height if yOffset < 0 { return } scroller.setContentOffset(CGPoint(x: 0, y: yOffset), animated: true) } } var body: some View { VStack { HStack { Button("Top") { scrollToTop() } Spacer() Button("Add Item") { items.append(Date.timeIntervalSinceReferenceDate.description) scrollToBottom() }.buttonStyle(.borderedProminent) Spacer() Button("Bottom") { scrollToBottom() } }.padding() // The source of all my pain ... List{ ForEach(items, id: \.self) { Text($0) } .onDelete { offsets in items.remove(atOffsets: offsets) } } .listStyle(.plain) .padding(.bottom, 50) } /* in iOS 16 List is backed by UICollectionView, no out of the box .introspectMethod ... nbd. */ .introspect(selector: TargetViewSelector.ancestorOrSiblingContaining, customize: { (collectionView: UICollectionView) in guard #available(iOS 16, *) else { return } self.scroller = collectionView }) /* in iOS 15 List is backed by UITableView ... */ .introspectTableView(customize: { tableView in guard #available(iOS 15, *) else { return } self.scroller = tableView }) } }
Oct ’22