I'm programatically updating the attributedText
of a UITextView
. Following the update I want to call setContentOffset
so that I can scroll to position the new text.
The problem I'm having is that there's a delay in the text view updating its text.
With the following code the debug log outputs the same value:
- (void)appendToTextView:(NSString*)text
{
CGFloat bottomOfCurrentContent = _pastedText.contentSize.height;
NSLog(@"Bottom of content, before = %f", bottomOfCurrentContent);
NSString* textViewText = text;
BOOL previouslyHadText = _pastedText.text.length > 0;
if (previouslyHadText) {
textViewText = [NSString stringWithFormat:@"%@\n%@", _pastedText.text, textViewText];
}
NSMutableParagraphStyle* paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineSpacing = _lineSpacing;
NSDictionary *attribute = @{ NSParagraphStyleAttributeName : paragraphStyle,
NSFontAttributeName : [UIFont systemFontOfSize:18.0] };
_pastedText.attributedText = [[ NSAttributedString alloc] initWithString:textViewText attributes:attribute];
if (previouslyHadText) {
CGFloat bottomOfNewContent = _pastedText.contentSize.height;
NSLog(@"Bottom of content, after = %f", bottomOfNewContent);
// Set content offset...
}
}
E.g., output:
2014-05-03 21:52:57.181 thisApp[7011:60b] Bottom of content, before = 244.000000
2014-05-03 21:52:57.182 thisApp[7011:60b] Bottom of content, after = 244.000000
If I artificially wait for the text view to complete its update the content is reported as expected...
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
CGFloat bottomOfNewContent = _pastedText.contentSize.height;
NSLog(@"Bottom of content, after = %f", bottomOfNewContent);
// Set content offset...
});
Output:
2014-05-03 23:12:39.694 thisApp[7050:60b] Bottom of content, before = 244.000000
2014-05-03 23:12:44.698 thisApp[7050:60b] Bottom of content, after = 451.000000
So, how do I get updated when the UITextView
s update has finished?
Update:
Based on the suggestion from indyfromoz, I can get a callback from the delegate method textViewDidChangeSelection
, following a programatic update to the text view. However, when that delegate method is called, the text view still hasn't finished updating.
If I drop the log statement in there:
- (void)textViewDidChangeSelection:(UITextView *)textView
{
CGFloat newContentHeight = textView.contentSize.height;
NSLog(@"bottom of new content: %f", newContentHeight);
}
The content height is reported the same as it was before the update...
I'm putting this down to a bug with UITextView
. I'll work around it for now and look at the code again in the future.