@@ -601,6 +601,9 @@ - (void)tryUpdatingActiveStyles {
601601 // style updates are emitted only if something differs from the previously active styles
602602 BOOL updateNeeded = NO ;
603603
604+ // active styles are kept in a separate set until we're sure they can be emitted
605+ NSMutableSet *newActiveStyles = [_activeStyles mutableCopy ];
606+
604607 // data for onLinkDetected event
605608 LinkData *detectedLinkData;
606609 NSRange detectedLinkRange = NSMakeRange (0 , 0 );
@@ -611,14 +614,14 @@ - (void)tryUpdatingActiveStyles {
611614
612615 for (NSNumber * type in stylesDict) {
613616 id <BaseStyleProtocol> style = stylesDict[type];
614- BOOL wasActive = [_activeStyles containsObject: type];
617+ BOOL wasActive = [newActiveStyles containsObject: type];
615618 BOOL isActive = [style detectStyle: textView.selectedRange];
616619 if (wasActive != isActive) {
617620 updateNeeded = YES ;
618621 if (isActive) {
619- [_activeStyles addObject: type];
622+ [newActiveStyles addObject: type];
620623 } else {
621- [_activeStyles removeObject: type];
624+ [newActiveStyles removeObject: type];
622625 }
623626 }
624627
@@ -678,6 +681,9 @@ - (void)tryUpdatingActiveStyles {
678681 if (updateNeeded) {
679682 auto emitter = [self getEventEmitter ];
680683 if (emitter != nullptr ) {
684+ // update activeStyles only if emitter is available
685+ _activeStyles = newActiveStyles;
686+
681687 emitter->onChangeState ({
682688 .isBold = [_activeStyles containsObject: @([BoldStyle getStyleType ])],
683689 .isItalic = [_activeStyles containsObject: @([ItalicStyle getStyleType ])],
@@ -990,6 +996,9 @@ - (void)manageSelectionBasedChanges {
990996 textView.typingAttributes = defaultTypingAttributes;
991997 }
992998 }
999+
1000+ // update active styles as well
1001+ [self tryUpdatingActiveStyles ];
9931002}
9941003
9951004- (void )handleWordModificationBasedChanges : (NSString *)word inRange : (NSRange )range {
@@ -1105,17 +1114,18 @@ - (void)_performRelayout
11051114 if (!textView) { return ; }
11061115
11071116 dispatch_async (dispatch_get_main_queue (), ^{
1108- NSRange wholeRange = NSMakeRange (0 , textView.textStorage .string .length );
1117+ NSRange wholeRange = NSMakeRange (0 , self-> textView .textStorage .string .length );
11091118 NSRange actualRange = NSMakeRange (0 , 0 );
1110- [textView.layoutManager invalidateLayoutForCharacterRange: wholeRange actualCharacterRange: &actualRange];
1111- [textView.layoutManager ensureLayoutForCharacterRange: actualRange];
1112- [textView.layoutManager invalidateDisplayForCharacterRange: wholeRange];
1119+ [self -> textView.layoutManager invalidateLayoutForCharacterRange: wholeRange actualCharacterRange: &actualRange];
1120+ [self -> textView.layoutManager ensureLayoutForCharacterRange: actualRange];
1121+ [self -> textView.layoutManager invalidateDisplayForCharacterRange: wholeRange];
11131122 });
11141123}
11151124
11161125- (void )didMoveToWindow {
11171126 [super didMoveToWindow ];
1118- [self scheduleRelayoutIfNeeded ];
1127+ // used to run all lifecycle callbacks
1128+ [self anyTextMayHaveBeenModified ];
11191129}
11201130
11211131// MARK: - UITextView delegate methods
@@ -1200,9 +1210,6 @@ - (void)textViewDidChangeSelection:(UITextView *)textView {
12001210
12011211 // manage selection changes
12021212 [self manageSelectionBasedChanges ];
1203-
1204- // update active styles
1205- [self tryUpdatingActiveStyles ];
12061213}
12071214
12081215// this function isn't called always when some text changes (for example setting link or starting mention with indicator doesn't fire it)
0 commit comments