From f80e2bd66d431374ff7497aa2359613f49fe4714 Mon Sep 17 00:00:00 2001 From: Fran Date: Tue, 1 Jul 2014 17:16:27 +0900 Subject: [PATCH] =?UTF-8?q?=EC=A4=84=EB=B0=94=EA=BF=88=20=EC=8B=9C=20?= =?UTF-8?q?=ED=95=9C=EA=B8=80=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=EB=90=9C=20=EC=BD=94=EB=93=9C=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://github.com/HansPinckaers/GrowingTextView/pull/86 --- class/HPGrowingTextView.h | 1 + class/HPGrowingTextView.m | 168 +++++++++++++++++++++----------------- 2 files changed, 94 insertions(+), 75 deletions(-) diff --git a/class/HPGrowingTextView.h b/class/HPGrowingTextView.h index b4c6a67..fcc06ee 100644 --- a/class/HPGrowingTextView.h +++ b/class/HPGrowingTextView.h @@ -68,6 +68,7 @@ BOOL animateHeightChange; NSTimeInterval animationDuration; + BOOL willRefreshHeight; //uitextview properties NSObject *__unsafe_unretained delegate; diff --git a/class/HPGrowingTextView.m b/class/HPGrowingTextView.m index 462164f..6215c11 100644 --- a/class/HPGrowingTextView.m +++ b/class/HPGrowingTextView.m @@ -107,6 +107,7 @@ -(void)commonInitialiser animateHeightChange = YES; animationDuration = 0.1f; + willRefreshHeight = NO; internalTextView.text = @""; @@ -257,97 +258,114 @@ - (void)setPlaceholderColor:(UIColor *)placeholderColor - (void)textViewDidChange:(UITextView *)textView { - [self refreshHeight]; + [self doRefreshHeight]; } -- (void)refreshHeight +- (void)doRefreshHeight { - //size of content, so we can set the frame of self - NSInteger newSizeH = [self measureHeight]; - if (newSizeH < minHeight || !internalTextView.hasText) { - newSizeH = minHeight; //not smalles than minHeight - } - else if (maxHeight && newSizeH > maxHeight) { - newSizeH = maxHeight; // not taller than maxHeight + // if we use korean keyboard, UITextView occasionally fires 2 textViewDidChange events simultaneously. + // for example, there is "버그버그ㅂ". we presse the "ㅓ" key. then text is changed to "버그버그버" + // but UITextView fires 2 textViewDidChange events. The first event is "버그버그ㅂ" to "버그버그". The second event is "버그버그" to "버그버그버". + // so we should use the last event of these events. + if (!willRefreshHeight) { + willRefreshHeight = YES; + [self performSelector:@selector(refreshHeight) withObject:nil afterDelay:0]; } - - if (internalTextView.frame.size.height != newSizeH) - { - // if our new height is greater than the maxHeight - // sets not set the height or move things - // around and enable scrolling - if (newSizeH >= maxHeight) - { - if(!internalTextView.scrollEnabled){ - internalTextView.scrollEnabled = YES; - [internalTextView flashScrollIndicators]; - } - - } else { - internalTextView.scrollEnabled = NO; +} + +- (void)refreshHeight +{ + @try { + //size of content, so we can set the frame of self + NSInteger newSizeH = [self measureHeight]; + if (newSizeH < minHeight || !internalTextView.hasText) { + newSizeH = minHeight; //not smalles than minHeight + } + else if (maxHeight && newSizeH > maxHeight) { + newSizeH = maxHeight; // not taller than maxHeight } - // [fixed] Pasting too much text into the view failed to fire the height change, - // thanks to Gwynne - if (newSizeH <= maxHeight) - { - if(animateHeightChange) { + if (internalTextView.frame.size.height != newSizeH) + { + // if our new height is greater than the maxHeight + // sets not set the height or move things + // around and enable scrolling + if (newSizeH >= maxHeight) + { + if(!internalTextView.scrollEnabled){ + internalTextView.scrollEnabled = YES; + [internalTextView flashScrollIndicators]; + } - if ([UIView resolveClassMethod:@selector(animateWithDuration:animations:)]) { + } else { + internalTextView.scrollEnabled = NO; + } + + // [fixed] Pasting too much text into the view failed to fire the height change, + // thanks to Gwynne + if (newSizeH <= maxHeight) + { + if(animateHeightChange) { + + if ([UIView resolveClassMethod:@selector(animateWithDuration:animations:)]) { #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000 - [UIView animateWithDuration:animationDuration - delay:0 - options:(UIViewAnimationOptionAllowUserInteraction| - UIViewAnimationOptionBeginFromCurrentState) - animations:^(void) { - [self resizeTextView:newSizeH]; - } - completion:^(BOOL finished) { - if ([delegate respondsToSelector:@selector(growingTextView:didChangeHeight:)]) { - [delegate growingTextView:self didChangeHeight:newSizeH]; + [UIView animateWithDuration:animationDuration + delay:0 + options:(UIViewAnimationOptionAllowUserInteraction| + UIViewAnimationOptionBeginFromCurrentState) + animations:^(void) { + [self resizeTextView:newSizeH]; } - }]; + completion:^(BOOL finished) { + if ([delegate respondsToSelector:@selector(growingTextView:didChangeHeight:)]) { + [delegate growingTextView:self didChangeHeight:newSizeH]; + } + }]; #endif + } else { + [UIView beginAnimations:@"" context:nil]; + [UIView setAnimationDuration:animationDuration]; + [UIView setAnimationDelegate:self]; + [UIView setAnimationDidStopSelector:@selector(growDidStop)]; + [UIView setAnimationBeginsFromCurrentState:YES]; + [self resizeTextView:newSizeH]; + [UIView commitAnimations]; + } } else { - [UIView beginAnimations:@"" context:nil]; - [UIView setAnimationDuration:animationDuration]; - [UIView setAnimationDelegate:self]; - [UIView setAnimationDidStopSelector:@selector(growDidStop)]; - [UIView setAnimationBeginsFromCurrentState:YES]; [self resizeTextView:newSizeH]; - [UIView commitAnimations]; + // [fixed] The growingTextView:didChangeHeight: delegate method was not called at all when not animating height changes. + // thanks to Gwynne + + if ([delegate respondsToSelector:@selector(growingTextView:didChangeHeight:)]) { + [delegate growingTextView:self didChangeHeight:newSizeH]; + } } - } else { - [self resizeTextView:newSizeH]; - // [fixed] The growingTextView:didChangeHeight: delegate method was not called at all when not animating height changes. - // thanks to Gwynne - - if ([delegate respondsToSelector:@selector(growingTextView:didChangeHeight:)]) { - [delegate growingTextView:self didChangeHeight:newSizeH]; - } } - } - } - // Display (or not) the placeholder string - - BOOL wasDisplayingPlaceholder = internalTextView.displayPlaceHolder; - internalTextView.displayPlaceHolder = self.internalTextView.text.length == 0; - - if (wasDisplayingPlaceholder != internalTextView.displayPlaceHolder) { - [internalTextView setNeedsDisplay]; + } + // Display (or not) the placeholder string + + BOOL wasDisplayingPlaceholder = internalTextView.displayPlaceHolder; + internalTextView.displayPlaceHolder = self.internalTextView.text.length == 0; + + if (wasDisplayingPlaceholder != internalTextView.displayPlaceHolder) { + [internalTextView setNeedsDisplay]; + } + + + // scroll to caret (needed on iOS7) + if ([self respondsToSelector:@selector(snapshotViewAfterScreenUpdates:)]) + { + [self performSelector:@selector(resetScrollPositionForIOS7) withObject:nil afterDelay:0.1f]; + } + + // Tell the delegate that the text view changed + if ([delegate respondsToSelector:@selector(growingTextViewDidChange:)]) { + [delegate growingTextViewDidChange:self]; + } } - - - // scroll to caret (needed on iOS7) - if ([self respondsToSelector:@selector(snapshotViewAfterScreenUpdates:)]) - { - [self performSelector:@selector(resetScrollPositionForIOS7) withObject:nil afterDelay:0.1f]; + @finally { + willRefreshHeight = NO; } - - // Tell the delegate that the text view changed - if ([delegate respondsToSelector:@selector(growingTextViewDidChange:)]) { - [delegate growingTextViewDidChange:self]; - } } // Code from apple developer forum - @Steve Krulewitz, @Mark Marszal, @Eric Silverberg