diff --git a/Signal/src/ViewControllers/ConversationView/ConversationCollectionView.m b/Signal/src/ViewControllers/ConversationView/ConversationCollectionView.m index b973ae637..8d823c056 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationCollectionView.m +++ b/Signal/src/ViewControllers/ConversationView/ConversationCollectionView.m @@ -12,6 +12,11 @@ NS_ASSUME_NONNULL_BEGIN - (void)setFrame:(CGRect)frame { + if (frame.size.width == 0 || frame.size.height == 0) { + // Ignore iOS Auto Layout's tendency to temporarily zero out the + // frame of this view during the layout process. + return; + } BOOL isChanging = !CGSizeEqualToSize(frame.size, self.frame.size); if (isChanging) { [self.layoutDelegate collectionViewWillChangeLayout]; @@ -24,6 +29,11 @@ NS_ASSUME_NONNULL_BEGIN - (void)setBounds:(CGRect)bounds { + if (bounds.size.width == 0 || bounds.size.height == 0) { + // Ignore iOS Auto Layout's tendency to temporarily zero out the + // frame of this view during the layout process. + return; + } BOOL isChanging = !CGSizeEqualToSize(bounds.size, self.bounds.size); if (isChanging) { [self.layoutDelegate collectionViewWillChangeLayout]; diff --git a/Signal/src/ViewControllers/ConversationView/ConversationInputToolbar.m b/Signal/src/ViewControllers/ConversationView/ConversationInputToolbar.m index a9140950f..caf420545 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationInputToolbar.m +++ b/Signal/src/ViewControllers/ConversationView/ConversationInputToolbar.m @@ -28,6 +28,7 @@ static void *kConversationInputTextViewObservingContext = &kConversationInputTex @property (nonatomic) BOOL shouldShowVoiceMemoButton; @property (nonatomic) NSArray *contentContraints; +@property (nonatomic) NSValue *lastTextContentSize; #pragma mark - Voice Memo Recording UI @@ -269,6 +270,7 @@ static void *kConversationInputTextViewObservingContext = &kConversationInputTex [rightButton setContentHuggingHigh]; [leftButton setCompressionResistanceHigh]; [rightButton setCompressionResistanceHigh]; + [self.inputTextView setCompressionResistanceLow]; [self.inputTextView setContentHuggingLow]; OWSAssert(leftButton.superview == self.leftButtonWrapper); @@ -311,7 +313,10 @@ static void *kConversationInputTextViewObservingContext = &kConversationInputTex [rightButton autoPinEdgeToSuperviewEdge:ALEdgeBottom], ]; - [self layoutIfNeeded]; + // Layout immediately, unless the input toolbar hasn't even been laid out yet. + if (self.bounds.size.width > 0 && self.bounds.size.height > 0) { + [self layoutIfNeeded]; + } } - (void)ensureShouldShowVoiceMemoButton @@ -668,8 +673,18 @@ static void *kConversationInputTextViewObservingContext = &kConversationInputTex if (context == kConversationInputTextViewObservingContext) { if (object == self.inputTextView && [keyPath isEqualToString:NSStringFromSelector(@selector(contentSize))]) { - - [self ensureContentConstraints]; + CGSize textContentSize = self.inputTextView.contentSize; + NSValue *_Nullable lastTextContentSize = self.lastTextContentSize; + self.lastTextContentSize = [NSValue valueWithCGSize:textContentSize]; + + // Update view constraints, but only when text content size changes. + // + // NOTE: We use a "fuzzy equals" comparison to avoid infinite recursion, + // since ensureContentConstraints can affect the text content size. + if (!lastTextContentSize || fabs(lastTextContentSize.CGSizeValue.width - textContentSize.width) > 0.1f + || fabs(lastTextContentSize.CGSizeValue.height - textContentSize.height) > 0.1f) { + [self ensureContentConstraints]; + } } } }