0

I understand this is a duplicate of this question, but the question seems abandoned, the asker is not providing feedback and the current answers have not worked for me.

I currently have a simple app whose main view contains a UIScrollView. When the app is first installed and run, there is no scroll behaviour and the view is stuck at the top of the content view, which is not the intended functionality. Interacting with the app by rotating the device, touching in a text field or touching a segmented control all correct the scroll functionality (i.e. give the ability to scroll to the bottom of the content view):

Why is this behaviour happening?
How can it be fixed?

Details:

Once the app has been interacted with, it can be put in the background and reopened without losing the scroll functionality. Manually terminating the app from the background and reopening it will re-trigger the problem. The end goal is to have the scroll functionality work correctly and immediately without the user having to perform an arbitrary ritual to unlock part of the app's functionality (Very strongly discouraged in Apple's HMI guidelines).

The UIScrollView (scrollView) in question is embedded in the topmost UIView, and it has a UIView (scrollContentView) as a child. The scrollView's contentSize.height is defined programmatically in my viewWillLayoutSubviews() function, and this is the height that is used by the UIScrollView once one of the aforementioned actions is taken:

override func viewWillLayoutSubviews()
{
   super.viewWillLayoutSubviews();

   // (This is just setting a child table of the scrollView's height)
   // Set the goal table's height to the height of its contents
   formulaTableHeightConstaint.constant = getGoalTableHeight();

   scrollView.contentSize.height = getGoalTableHeight() + Constants.formHeight;
}

At the end of the viewWillLayoutSubviews() function, if I print the scrollView.contentSize.height, it shows a large value around 2000, and printing the scrollView.frame.size.height shows a value around 600.

Attempts:

I have tried to use scrollView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: SomeArbitraryValues, right: 0). This allows scrolling immediately when the app is first opened, but the behaviour is unintuitive in that, even setting the bottom to values that should be smaller than the scroll content height, allows the app to scroll a good distance past the bottom of the content. Just the same, setting smaller values usually prevents the view from scrolling to the bottom of the content. From what I understand from the documentation, this seems like a slightly unrelated (and maybe smelly) property to use to fix this problem (Though I could be wrong). As well, even though messing with the contentInset seems to trigger correct scrolling behaviour, printing the contentInset value before and after the scroll works shows no changes to it occurred.

I have also tried adding a height constraint to the scrollContentView and setting that height programmatically to no avail.

Any help on the matter is greatly appreciated.

Community
  • 1
  • 1
loaner9
  • 300
  • 4
  • 12
  • My guess is that something after `willLayoutSubviews` that is only run on App Launch is changing the values that your scrollview has. I would add a function somewhere that you can manually run to check the scrollview content height when the scrollview is not working properly. If it still shows proper values in the inactive state, then I'm way off base and have no idea... – Putz1103 Jul 15 '16 at 16:17
  • So I ran multiple checks in multiple locations throughout the code, and in the inactive state, the `scrollView.contentSize.height` always shows a good value of 2497.5, so it doesn't seem to be the problem. Thanks for the suggestion :) – loaner9 Jul 15 '16 at 16:30
  • Check also the height of the scrollview itself in those places. It might be larger than the content size, or have height zero. Both would disable scrolling. – fishinear Jul 15 '16 at 16:44
  • I checked every size property that I could think of, of the scrollView in multiple locations, and while inactive, the frame.size or the bounds.size are always showing {600, 600} – loaner9 Jul 15 '16 at 16:49

1 Answers1

1

You should set the contentSize height as follows:

scrollView.contentSize = CGSizeMake(width, getGoalTableHeight() + Constants.formHeight); 

scrollView.contentSize.height refers to the height member of the struct that is returned from the contentSize method.

fishinear
  • 6,101
  • 3
  • 36
  • 84
  • That is a very good point. Setting only the height might not fire off the internal methods to tell the UI that something changed and it can scroll now. – Putz1103 Jul 15 '16 at 16:35
  • I replaced `scrollView.contentSize.height = getGoalTableHeight() + Constants.formHeight;` with `scrollView.contentSize = CGSizeMake(width, getGoalTableHeight() + Constants.formHeight);` still to no avail. Excellent suggestion, thanks :) – loaner9 Jul 15 '16 at 16:40