UICollectionView compositional layout not scrolling horizontal items back to beginning - uicollectionview

When I try to refresh the data in my UICollectionView that's using iOS 13's new compositional layout, I can't find a way to make horizontally scrolling sections scroll back to their starting point.
If I call applySnapshot on the data source, the section's data refreshes, but it doesn't scroll back to the beginning. If I call scrollToRowAtIndexPath on each section, it will go back to the first row but it ignores the content insets on that section, which doesn't look good.
I tried applying an empty snapshot before applying the real one and that does work, but I intermittently get crashes in UICollectionCompositionalLayoutSolver saying "invalid section - null".
So what's the proper way to reset the horizontal scrolling on a collection view that's using compositional layout? I'm sure there's something I'm missing.

I am not sure about your question in detail, but I am doing an initial scroll to the current object using this method, that does beautifully center the scroll to object:
collectionView.scrollToItem(at: IndexPath(item: indexOfCurrent, section: sectionIndex), at: .centeredHorizontally, animated: true)

Related

PDFView getting/setting scroll position

Good Morning,
I have a PDFView in an NSSplitView. I've implemented zooming and scrolling, using trackpad gestures. However whenever I reload the PDF, the scroll position resets to the top left corner. This is ok if the full page is shown, but if the PDF is zoomed and only partly visible, this can move the section of interest out of the view.
I've tried using enclosingScrollView but that returns nil. I've tried digging through the subviews to find the NSScrollView, the NSScrollers, NSClipView many of the displayRect and related properties are readonly. I've tried reading the verticalPageScroll and verticalLineScroll but they only every return 10.0.
I seem to be left with systematically going through the class properties and methods of each subview and see if they contain the data.
I'm sure someone knows how to get and set this.
Thanks.
Mark

NSCollectionView loses scrollbars after changing minItemSize until view gets resized

I have an NSCollectionView with a vertical NSCollectionViewFlowLayout. I display rectangular icons in it.
I also have a slider in the UI, and when that changes, I adjust the minItemSize, which I then use in collectionView:itemForRepresentedObjectAtIndexPath: to create an equally sized NSImageView to the returned NSCollectionViewItem's imageView. Then I reload the view by invoking reloadData.
After that, the view shows the icons in the new size as intended.
The problem is, provided I have more data to show than fits into the current scoll view, that when the General System Preferences are set to Show scroll bars: When scrolling, the scrollbar disappears after reloading the collection view, and trying to scroll with the trackpad leads to a bounce that's telling me that the scroll view thinks that the content is just what's visible, nothing more to scroll.
But as soon as I resize the window, which also resizes the collection view inside, the scrollbars come back.
Curiously, if the System Prefs are set to Show scroll bars: Always, then the issue does not appear and the scrolling always works, and the scrollbars always remain visible.
I've tried a lot of things to trigger the re-calculation of the scroll view, such as invalidating the layout of the collection view's layout, the scroll view itself, its content view, and also tried to set their needsLayout to true. Nothing makes this work.
Update: The potential duplicate (NSCollectionView does not scroll items past initial visible rect), neither the collectionView.setFrameSize: nor the window.setFrame: suggestions work for my case (I tried adding these line before and after reloadData).
Even if I force a resize of the window like this, it doesn't bring the scrollbars back, only a manual dragging of the window edges does:
[self.collectionView.window setFrame:NSInsetRect(self.view.window.frame, 1, 1) display:YES];
Also note that in my case, initially the scrolling works, just not after resizing and reloading.
Another finding: When I call selectItemsAtIndexPaths:scrollPosition: after reloadData, then the scrollbar comes back. But only if I pass a non-empty NSSet for the paths. And since I may not have selected any items, this isn't a permanent solution.
If no other ideas come up, I'll try to make a demo project.
I've solved it:
I had to delay the call to reloadData, e.g. by calling it from within the block code of dispatch_async(dispatch_get_main_queue(), ^{ ... });
Before the fix, I did call reloadData right from the setSliderValue: handler, which is bound to the slider's value. It appears that this didn't go well together.

Xcode UITextView Still not scrolling using storyboard

I am trying to initiate a scroll view in my UITextView and even though I seem to have selected the appropriate boxes, I can't seem to get the scrolling working. I have gone through multiple questions similar to this but none seem to have the answer.
I included an image of Xcode below:
Question 2: When I scroll down the majority of my text shows but the scrolling stops with two sentences or so left and I have to scroll down and hold it there to read. Any way I can fix this so it scrolls all the way to the bottom of the text?
Can you check the two boxes: Bounce Horizontally and Bounce Vertically and see what's happening? Sometimes your content are actually way bigger than your view, and they are touching a invisible outer box. If you can see they actually move, that means there is nothing wrong with touch or scroll, is just the view layout problem.
For the content issue, my guess is that the content size is not right, you can programmatically adjust it with textView.frame property, set it to a proper size, such as the frame of the window or the frame of the content, which are CGRect classes. Comment below to see if this can solve your second problem.
The text view will not scroll in storyboard, only the app. And the text view will scroll once the content in the text view exceeds the frame size.
If you're using iOS 7+, you can just turn on auto layout, pin each of the sides of the text view to the edge of its parent view, and it works fine without needing to do anything in code.

UICollectionView does not reveal all cells in Simulator

I am not very experienced with UICollectionView and Auto-Layout.
I have a very basic UICollectionView inside a root view. The root view seems to have a Navigation Item.
I created a custom cell which is really a square in proper size to allow 2 such cells per row using the FlowLayout.
There are 8 such cells in the view - it is basically a grid. I have absolutely no constraints on the view.
The collection view occupies the entire size of the root view according to the IB and in the editor, the first cell is placed right under the navigation item which is perfect.
However, when I ran the app in the simulator and scrolled the collectionview all the way to the button, I see only a partial fragment of both cells in the last row. I can see I have scrolled all the way down...
Obviously there seems to be some sort of overflow...but I would have thought uicollectionview would automatically handle the overflow and make all the cells visible?
When I set number of items in IB I can see that the cells in the last row are only partially visible.
Seems like content size of the collection view is not right - that's my guess..
What do I need to do to adjust things in IB so that all of my cells are visible...I do not want to hardcode any values in the code...
Thanks.
Solved. It turns out simulator does not show the entire collection view...the same shows fine on the device... What a headache...

Strange UIContainerView autolayout rotation behavior

I have a view controller that consists of two child UIContainerViews, one of which is fixed-width, and the other which dynamically adjusts its width based on portrait vs landscape mode. Both contain UITableViews.
For some reason, if the screen loads in portrait orientation it renders fine. However if it loads in landscape and then rotates to portrait, the second (dynamic) table gets all screwy and thinks it's wider than it is/should be, letting you scroll it horizontally which it should not be doing.
The cells of the tableView all size properly and stick to the left side of this "too wide" tableView. However, if I color the background of the tableview pink, I can see the whole thing is extending into this too wide zone.
It's baffling me what's going on here. Shouldn't autolayout be the same regardless of which orientation the view controller was loaded as?
If I log the widths in a viewDidRotate... handler, everything appears to have the correct width, yet it's still rendering in this bizarre way.
Is there perhaps I way I can just force the container view to re-lay it self out?
Update: It is the contentSize of the tableView that is getting messed up. All the other widths are correct when logged, but the contentSize.width is way off. The good news is I can just manually set this back to what it should be and everything works great! However it doesn't answer the question as to why it's happening in the first place or what I'm doing wrong (if anything).
Here's a screenshot:
In order to force a UITableView to (re)calculate its content size, you may use layoutIfNeeded method. It traverses through the view hierarchy and lays out the subviews immediately, so content size is set properly.
Instead of setting the size manually, call this method for your table view.