automaticallyAdjustsScrollViewInsets doesn't work in embedded UITableViewController with UITableView - ios

When you have a UITableView inside a UIViewController, you have to turn off the automaticallyAdjustsScrollViewInsets flag (either in code or storyboard editor) to get the top space to not avoid the top bar. I now have a child UIViewController using an "embed" seque inside of a child view which contains a UITableView. I am seeing the "space" (the yellow area) yet I cleared all the flags in the embedded UIViewController and even cleared the flag manually in prepareForSeque, yet the space remains. Is there something else one has to do, or is this a bug?

Had this issue this morning.
Turns out, you need to uncheck automaticallyAdjustsScrollViewInsets property from parentViewController instead of child when you are using embedded view controller mode like you did.
Here is my UI structure:
ParentViewController has a container view which point to ChildViewController (subclass of UITableViewController).
Uncheck automaticallyAdjustsScrollViewInsets in ChildViewController: doesn't work
Uncheck automaticallyAdjustsScrollViewInsets in ParentViewController: works!

I have been struggling with this for hours until I realized that the answer by #user3188985 was what was happening, though the solution did not work for me.
This is because I have two contained view controllers that each contain scrollViews, and I want one to adjust, and one not, what to do?
Well if you turn off auto adjustment in the parent controller, then you must manually adjust the one scrollView that you need, e.g. setting contentInset on appropriate cases.
If you leave on auto adjustment in the parent, I have found that a dummy scrollView, with a zero frame, hidden, all scroll properties set to NO, and if it is before your visible/enabled scrollView in the child view controller view hierarchy, then it will receive the auto adjustment, and leave your visible scrollView view alone.
Alternatively, you can just have your contained view controller's top most view be a scrollView with scrolling disabled, and have it contain another scrollView with scrolling enabled, this will achieve the same thing as the "dummy" approach.
What you can see here, is that the auto adjustment flag of only the parent view controller is taken into account, but it's own view controller hierarchy is traversed to find scrollViews to adjust in each contained controller. This is simply unwanted UIKit behavior. It would be nice each child controller's auto adjust setting was checked before deciding to mess with it :/

Related

Change constraints that are set on the parent view from within the child view

I am having the following problem over and over again and I am looking for a clean solution to do this.
I have multiple views: a parent view (my rootView, controlled by my basic UIViewController) and a descendant view (a UICollectionViewCell in a UICollectionView which is a subview of my rootView).
The size of the UICollectionView is relative to the size of my rootView: in the UIViewController of the rootView, where I created the UICollectionView, I also created constraints (between the rootView and the UICollectionView) and added them to the rootView.
When a button is tapped in the UICollectionViewCell I want to change the size of the UICollectionView. Therefore I need to alter the constraints that are set on my rootView.
I have been told that accessing the constraints of the rootView via a downcast of the UIViewController and changing them this way is dirty, because having a view talk back to its (parent)controller is wrong.
How am I supposed to act in such a situation? How can I make the controller react to the view without the view talking to the controller? A point in the right direction would be great!
After your edits, it sounds like you only have one view controller in play here. In that case, life is good. The logic to manipulate the constraints that control your collection view belongs in the view controller.
You want to pass the button taps to your view controller, and have it handle resizing the collection view.
How are you handling button taps?

Embedding a view with subviews in another parent view and keeping constraints (IB)

I have a scene in storyboard with several subviews for which I already set a lot of constraints in Interface Builder. These subviews are directly children of the view controller's view. Now I realize that I need the whole view + subviews be contained in a full-screen UIScrollView to handle scrolling of the content when the keyboard is shown. But if I simply move all the subviews inside the scroll view, I loose the constraints that referred to "superview" and I get a mess.
Is there any way to migrate the constraints regarding the previous "superview" (view controller's view) to the new parent scroll view (which is the child of the "superview")?
Thanks
No there is no way to do this. The constraints between the view controller's view and the subviews are as you know broken when you move your subviews into another subview/view. AFIAK the biggest reason for this is you could end up with subviews that have constraints which relate to views on longer in their
view hierarchy which is a violate of the constraints lay out system.

Why content insets of a UITableView inside a UIPageViewController get messy right after an interaction?

I've created a Page-Based Application and hacked it a bit for some experiments; my simple aim is to have a UIPageViewController whose pages will contain a UIViewController holding a UITableView (after further inspection, the outcome of my experiment is the same if I use a UITableViewController instead).
To do this I've simply edited the project template, and added the UIPageViewController as an embedded view of the RootViewController using Storyboard's ContainerView object, as you can see in this screenshot:
Every controller is configured via storyboard to automatically adjust scroll view's content inset, and if I start the project with this configuration everything looks fine, and the DataViewController's tableview has its content insets properly adjusted right under the navigation bar as expected; however, as the user makes an interaction with the tableview, the content insets break and the tableview underlaps the navigation bar:
I have been able to fix this by manually setting the content insets in DataViewController's viewDidLayoutSubview method, and by disabling Adjusts Scroll View Insets on any controller, so I don't need this as an answer to solve my problem.
My question is why the content insets are properly set right after the first controller gets loaded from the storyboard the first time, and why they break after any kind of user interaction.
If you need to test it directly, here's a link to the project
I'm not 100% sure it's what you're running into, but here's some explanation regarding your setup:
By default, UIViewControllers tend to be configured to extend their content behind non-opaque bars, and to adjust scroll view insets. In your setup above this means that the container VC:
Extends its content so as to appear behind the navigation bar
Sets its scrollview's .contentInset and .scrollIndicatorInsets to be the same height as the navigation bar
"But, ah!" I hear you say, "that container view controller doesn't have a scroll view". Well this is the tricky bit:
It seems UIViewController's definition of "my scroll view" is rather simplistically, "the first scroll view I come to when searching down through my view hierarchy".
UIPageViewController happens to be implemented using a scroll view. So the container VC finds that scroll view, and adjusts its top insets. This is not really what you want; it confuses the page controller, and tends to upset layout at some point.
The simple solution there is simply to turn off .automaticallyAdjustsScrollViewInsets for the container view controller.
You then need to solve the next problem of your table view needing some kind of top insets to account for the navigation bar. So far it seems to me the best way to do this is manually either in the storyboard, or code.
Found an elegant solution:
From your storyboard, select your UIPageViewController
In the Attributes inspector, uncheck the option ViewController => Extend Edges => Under Top Bars
That's all, no weird UI hacks
Have you tried fixing the Auto Layout constraint in the container view of the Root view controller in the Storyboard (that is, the top space constraint should be set related to the Top Layout Guide and not the Superview, with constant = 0)?
You will only lose the effect of the Table View scrolling under the Navigation Bar

Tapping status bar doesn't scroll table view to top

Ok, I've read almost every single post about this issue, and they all say the same thing:
In the whole view hierarchy, only one scroll view (or subclass) should have scrollsToTop set to YES and the rest should be NO. When my view loads, I recursively iterate the whole view hierarchy just as many answers suggest, setting scrollsToTop to NO, then I only set my table view's scrollsToTop to YES, but still, it doesn't scroll when I tap the status bar. I've overridden:
-(BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView{
return YES;
}
But it's not even called even though my view controller is the scroll view delegate of my table view.
I do have cells with text views, and when the container cell awakes from nib, I also set their scrollsToTop property to NO immediately, and there are no other views deriving from scroll view.
Why would it not work?
For what it's worth, I've never set scrollsToTop on any table view controller I've ever used, and they all do this by default. Maybe all this recursive view hierarchy stuff is what is actually causing the problem. I just looked at all the apps I've written, and all of them work fine without ever touching scrollsToTop, and many of them have embedded scrollViews/textViews/etc in them. Perhaps try commenting out all that scrollsToTop code and trying it then?
Otherwise, how are you building this tableview? Is it with a nib or is this a normal UITableViewController?

Embed UITableView in Scrollview

I know Apple don't recommend to Embed UITableView in UIScrollview.
So this is what I am trying to do:
I have a registration form with fields embedded in UIScrollview,
for some fields I create a drop menu by presenting UITableView, the problem is when the UITableView appears with my object the didSelectRowAtIndexPath not responding.
If there is another way it I will happy to hear, if not how can I fix it in the Current situation , thanks.
Don't add the table as a subview of the scroll view, add it as a subview of the superview of the scroll view (and, consider adding it into a container view which detects touches outside the table to dismiss it from the screen without any selection being made).
If your 'root' view for the controller is the scroll view, change your view hierarchy to use a plain view as the root and have the scroll view as a subview of that.
You may also want to use bringSubviewToFront: to ensure that the presentation is correct.

Resources