@@ -605,6 +605,9 @@ - (void)tryUpdatingActiveStyles {
605605 // style updates are emitted only if something differs from the previously active styles
606606 BOOL updateNeeded = NO ;
607607
608+ // active styles are kept in a separate set until we're sure they can be emitted
609+ NSMutableSet *newActiveStyles = [_activeStyles mutableCopy ];
610+
608611 // data for onLinkDetected event
609612 LinkData *detectedLinkData;
610613 NSRange detectedLinkRange = NSMakeRange (0 , 0 );
@@ -615,14 +618,14 @@ - (void)tryUpdatingActiveStyles {
615618
616619 for (NSNumber * type in stylesDict) {
617620 id <BaseStyleProtocol> style = stylesDict[type];
618- BOOL wasActive = [_activeStyles containsObject: type];
621+ BOOL wasActive = [newActiveStyles containsObject: type];
619622 BOOL isActive = [style detectStyle: textView.selectedRange];
620623 if (wasActive != isActive) {
621624 updateNeeded = YES ;
622625 if (isActive) {
623- [_activeStyles addObject: type];
626+ [newActiveStyles addObject: type];
624627 } else {
625- [_activeStyles removeObject: type];
628+ [newActiveStyles removeObject: type];
626629 }
627630 }
628631
@@ -682,6 +685,9 @@ - (void)tryUpdatingActiveStyles {
682685 if (updateNeeded) {
683686 auto emitter = [self getEventEmitter ];
684687 if (emitter != nullptr ) {
688+ // update activeStyles only if emitter is available
689+ _activeStyles = newActiveStyles;
690+
685691 emitter->onChangeState ({
686692 .isBold = [_activeStyles containsObject: @([BoldStyle getStyleType ])],
687693 .isItalic = [_activeStyles containsObject: @([ItalicStyle getStyleType ])],
@@ -994,6 +1000,9 @@ - (void)manageSelectionBasedChanges {
9941000 textView.typingAttributes = defaultTypingAttributes;
9951001 }
9961002 }
1003+
1004+ // update active styles as well
1005+ [self tryUpdatingActiveStyles ];
9971006}
9981007
9991008- (void )handleWordModificationBasedChanges : (NSString *)word inRange : (NSRange )range {
@@ -1109,17 +1118,18 @@ - (void)_performRelayout
11091118 if (!textView) { return ; }
11101119
11111120 dispatch_async (dispatch_get_main_queue (), ^{
1112- NSRange wholeRange = NSMakeRange (0 , textView.textStorage .string .length );
1121+ NSRange wholeRange = NSMakeRange (0 , self-> textView .textStorage .string .length );
11131122 NSRange actualRange = NSMakeRange (0 , 0 );
1114- [textView.layoutManager invalidateLayoutForCharacterRange: wholeRange actualCharacterRange: &actualRange];
1115- [textView.layoutManager ensureLayoutForCharacterRange: actualRange];
1116- [textView.layoutManager invalidateDisplayForCharacterRange: wholeRange];
1123+ [self -> textView.layoutManager invalidateLayoutForCharacterRange: wholeRange actualCharacterRange: &actualRange];
1124+ [self -> textView.layoutManager ensureLayoutForCharacterRange: actualRange];
1125+ [self -> textView.layoutManager invalidateDisplayForCharacterRange: wholeRange];
11171126 });
11181127}
11191128
11201129- (void )didMoveToWindow {
11211130 [super didMoveToWindow ];
1122- [self scheduleRelayoutIfNeeded ];
1131+ // used to run all lifecycle callbacks
1132+ [self anyTextMayHaveBeenModified ];
11231133}
11241134
11251135// MARK: - UITextView delegate methods
@@ -1204,9 +1214,6 @@ - (void)textViewDidChangeSelection:(UITextView *)textView {
12041214
12051215 // manage selection changes
12061216 [self manageSelectionBasedChanges ];
1207-
1208- // update active styles
1209- [self tryUpdatingActiveStyles ];
12101217}
12111218
12121219// 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