2

I have a modal screen with a Page View. The Page View loads the pages using storyboard IDs. All pages are the same. Each page has a UITextView with some text and its scrollable. At viewDidLoad the text is set. When the text is set, it automatically scrolls to bottom, so at viewDidAppear I invoke [self.textField setContentOffset:CGPointZero animated:animated];.

This works fine, except for the first page. Due to a bug, in viewDidLayoutSubviews I need toggle scrollEnabled for the UITextView. However, when the first page is loaded, viewDidAppear is for some reason called prior to viewLayoutSubviews, which has the side-effect of scrolling the UITextView to bottom, probably due to the toggling. If I scroll past the first page and then return to first page, it works as expected (then the calling order is the same as for the other pages).

Some other things I've tried:

  • Setting the text in async_dispatch on main queue in viewDidLoad.
  • Calling [self.textField scrollRangeToVisible:NSMakeRange(0, 0)]; at viewDidLayoutSubviews
  • Various combinations of scrollRangeToVisible and setContentOffset.
  • Setting self.automaticallyAdjustsScrollViewInsets = NO; in viewDidLoad.
  • Trying to scroll the view after setting the text (using either of the above methods)

Anyone have an idea on how to fix this?

Here is the code for the view controller:

- (void)viewDidLoad {
    [super viewDidLoad];

    // Get help string
    NSMutableAttributedString *attributedString = <fetch text from external source>

    // Set text
    self.textField.attributedText = attributedString;
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    [self.textField setContentOffset:CGPointZero animated:animated];
}

- (void)viewDidLayoutSubviews {

    [super viewDidLayoutSubviews];

    self.textField.scrollEnabled = NO;
    self.textField.scrollEnabled = YES;
}
Community
  • 1
  • 1
T'n'E
  • 598
  • 5
  • 17
  • `viewWillAppear:` is usually a good place to do last-minute adjustments before something shows up on screen, I think this is what you are looking for – Alex Jan 04 '17 at 14:15
  • Its a good guess, but in this case `viewDidLayoutSubviews` is called after `viewWillAppear`, and the forced scrolling must be done after the layout (but for some reason not in layout callback). `viewDidAppear` is called after `viewDidLayoutSubviews`, so that works. – T'n'E Jan 04 '17 at 14:48
  • Your question title says `UITextView` but you repeatedly refer to `UITextField` in your question: which is it? – Alex Jan 04 '17 at 14:52
  • Whoops, good catch. Its supposed to be UITextView. – T'n'E Jan 04 '17 at 15:47
  • I just realized your code says 'fetch text from external source' - is this an async fetch that's taking a few milliseconds to complete? – Alex Jan 04 '17 at 16:26
  • No, it's just reading an RTF-file. – T'n'E Jan 04 '17 at 21:09

1 Answers1

0

This works for me. I'm loading a UIViewController with a UITextView. I assign the text in viewDidLoad and then set the contentOffset in viewWillAppear.

class ViewController: UIViewController {
    @IBOutlet weak var textView: UITextView!
    override func viewDidLoad() {
        super.viewDidLoad()
        textView.text = "Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda."
    }
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        textView.contentOffset = .zero
    }
}
Alex
  • 3,861
  • 5
  • 28
  • 44
  • Does this work if you toggle `scrollEnabled` off and on in `viewDidLoad`? – T'n'E Jan 04 '17 at 21:12
  • Yes. Maybe add more code with how your presenting the controllers or loading the text if you still have problems. – Alex Jan 05 '17 at 14:40