修改 我已经退出界面,然后从新进入界面弹起键盘,为什么撤销删除按钮显示?
This commit is contained in:
@@ -65,6 +65,8 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
|||||||
|
|
||||||
- (void)viewDidLoad {
|
- (void)viewDidLoad {
|
||||||
[super viewDidLoad];
|
[super viewDidLoad];
|
||||||
|
// 撤销删除是“上一段删除操作”的临时状态;键盘被系统回收/重建或跨页面回来时应当清空,避免误显示。
|
||||||
|
[[KBBackspaceUndoManager shared] registerNonClearAction];
|
||||||
[self setupUI];
|
[self setupUI];
|
||||||
self.suggestionEngine = [KBSuggestionEngine shared];
|
self.suggestionEngine = [KBSuggestionEngine shared];
|
||||||
self.currentWord = @"";
|
self.currentWord = @"";
|
||||||
@@ -93,11 +95,20 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
|||||||
|
|
||||||
- (void)viewWillAppear:(BOOL)animated{
|
- (void)viewWillAppear:(BOOL)animated{
|
||||||
[super viewWillAppear:animated];
|
[super viewWillAppear:animated];
|
||||||
|
// 进入/重新进入输入界面时,清理上一次会话残留的撤销状态与缓存,避免显示“撤销删除”但实际上已不可撤销。
|
||||||
|
[[KBBackspaceUndoManager shared] registerNonClearAction];
|
||||||
|
[[KBInputBufferManager shared] resetWithText:@""];
|
||||||
[[KBLocalizationManager shared] reloadFromSharedStorageIfNeeded];
|
[[KBLocalizationManager shared] reloadFromSharedStorageIfNeeded];
|
||||||
[[KBInputBufferManager shared] seedIfEmptyWithContextBefore:self.textDocumentProxy.documentContextBeforeInput
|
// 注意:微信/QQ 等宿主的 documentContext 可能是“截断窗口”,这里只更新 liveText,不要把它当作全文 manualSnapshot。
|
||||||
|
[[KBInputBufferManager shared] updateFromExternalContextBefore:self.textDocumentProxy.documentContextBeforeInput
|
||||||
after:self.textDocumentProxy.documentContextAfterInput];
|
after:self.textDocumentProxy.documentContextAfterInput];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)viewWillDisappear:(BOOL)animated {
|
||||||
|
[super viewWillDisappear:animated];
|
||||||
|
[[KBBackspaceUndoManager shared] registerNonClearAction];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)textDidChange:(id<UITextInput>)textInput {
|
- (void)textDidChange:(id<UITextInput>)textInput {
|
||||||
[super textDidChange:textInput];
|
[super textDidChange:textInput];
|
||||||
[[KBInputBufferManager shared] updateFromExternalContextBefore:self.textDocumentProxy.documentContextBeforeInput
|
[[KBInputBufferManager shared] updateFromExternalContextBefore:self.textDocumentProxy.documentContextBeforeInput
|
||||||
|
|||||||
@@ -11,11 +11,11 @@
|
|||||||
|
|
||||||
static const NSTimeInterval kKBBackspaceLongPressMinDuration = 0.35;
|
static const NSTimeInterval kKBBackspaceLongPressMinDuration = 0.35;
|
||||||
static const NSTimeInterval kKBBackspaceRepeatInterval = 0.06;
|
static const NSTimeInterval kKBBackspaceRepeatInterval = 0.06;
|
||||||
static const NSTimeInterval kKBBackspaceChunkStartDelay = 1.0;
|
static const NSTimeInterval kKBBackspaceChunkStartDelay = 0.6;
|
||||||
static const NSTimeInterval kKBBackspaceChunkRepeatInterval = 0.1;
|
static const NSTimeInterval kKBBackspaceChunkRepeatInterval = 0.1;
|
||||||
static const NSTimeInterval kKBBackspaceChunkFastDelay = 1.4;
|
static const NSTimeInterval kKBBackspaceChunkFastDelay = 1.2;
|
||||||
static const NSInteger kKBBackspaceChunkSize = 6;
|
static const NSInteger kKBBackspaceChunkSize = 8;
|
||||||
static const NSInteger kKBBackspaceChunkSizeFast = 12;
|
static const NSInteger kKBBackspaceChunkSizeFast = 16;
|
||||||
static const CGFloat kKBBackspaceClearLabelCornerRadius = 8.0;
|
static const CGFloat kKBBackspaceClearLabelCornerRadius = 8.0;
|
||||||
static const CGFloat kKBBackspaceClearLabelHeight = 26.0;
|
static const CGFloat kKBBackspaceClearLabelHeight = 26.0;
|
||||||
static const CGFloat kKBBackspaceClearLabelPaddingX = 10.0;
|
static const CGFloat kKBBackspaceClearLabelPaddingX = 10.0;
|
||||||
@@ -210,34 +210,77 @@ typedef NS_ENUM(NSInteger, KBClearPhase) {
|
|||||||
whitespaceSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];
|
whitespaceSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];
|
||||||
asciiWordSet = [NSCharacterSet characterSetWithCharactersInString:
|
asciiWordSet = [NSCharacterSet characterSetWithCharactersInString:
|
||||||
@"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"];
|
@"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"];
|
||||||
punctuationSet = [NSCharacterSet punctuationCharacterSet];
|
NSMutableCharacterSet *punct = [[NSCharacterSet punctuationCharacterSet] mutableCopy];
|
||||||
|
// 补齐常见中文/全角标点(避免 chunk 总是只删 1 个符号)
|
||||||
|
[punct addCharactersInString:@",。!?;:、()【】《》“”‘’·…—"];
|
||||||
|
punctuationSet = [punct copy];
|
||||||
});
|
});
|
||||||
|
|
||||||
__block NSInteger deleteCount = 0;
|
__block NSInteger deleteCount = 0;
|
||||||
__block KBBackspaceChunkClass chunkClass = KBBackspaceChunkClassUnknown;
|
typedef NS_ENUM(NSInteger, KBBackspaceChunkPhase) {
|
||||||
|
KBBackspaceChunkPhaseWhitespace = 0,
|
||||||
|
KBBackspaceChunkPhasePunctuation,
|
||||||
|
KBBackspaceChunkPhaseCore
|
||||||
|
};
|
||||||
|
__block KBBackspaceChunkPhase phase = KBBackspaceChunkPhaseWhitespace;
|
||||||
|
__block KBBackspaceChunkClass coreClass = KBBackspaceChunkClassUnknown;
|
||||||
|
|
||||||
[context enumerateSubstringsInRange:NSMakeRange(0, context.length)
|
[context enumerateSubstringsInRange:NSMakeRange(0, context.length)
|
||||||
options:NSStringEnumerationByComposedCharacterSequences | NSStringEnumerationReverse
|
options:NSStringEnumerationByComposedCharacterSequences | NSStringEnumerationReverse
|
||||||
usingBlock:^(NSString *substring, __unused NSRange substringRange, __unused NSRange enclosingRange, BOOL *stop) {
|
usingBlock:^(NSString *substring, __unused NSRange substringRange, __unused NSRange enclosingRange, BOOL *stop) {
|
||||||
if (substring.length == 0) { return; }
|
if (substring.length == 0) { return; }
|
||||||
KBBackspaceChunkClass currentClass = KBBackspaceChunkClassOther;
|
if (deleteCount >= maxCount) {
|
||||||
if ([substring rangeOfCharacterFromSet:whitespaceSet].location != NSNotFound) {
|
|
||||||
currentClass = KBBackspaceChunkClassWhitespace;
|
|
||||||
} else if ([substring rangeOfCharacterFromSet:asciiWordSet].location != NSNotFound) {
|
|
||||||
currentClass = KBBackspaceChunkClassASCIIWord;
|
|
||||||
} else if ([substring rangeOfCharacterFromSet:punctuationSet].location != NSNotFound) {
|
|
||||||
currentClass = KBBackspaceChunkClassPunctuation;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chunkClass == KBBackspaceChunkClassUnknown) {
|
|
||||||
chunkClass = currentClass;
|
|
||||||
} else if (chunkClass != currentClass) {
|
|
||||||
*stop = YES;
|
*stop = YES;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KBBackspaceChunkClass currentClass = KBBackspaceChunkClassOther;
|
||||||
|
if ([substring rangeOfCharacterFromSet:whitespaceSet].location != NSNotFound) {
|
||||||
|
currentClass = KBBackspaceChunkClassWhitespace;
|
||||||
|
} else if ([substring rangeOfCharacterFromSet:punctuationSet].location != NSNotFound) {
|
||||||
|
currentClass = KBBackspaceChunkClassPunctuation;
|
||||||
|
} else if ([substring rangeOfCharacterFromSet:asciiWordSet].location != NSNotFound) {
|
||||||
|
currentClass = KBBackspaceChunkClassASCIIWord;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL consumed = NO;
|
||||||
|
while (!consumed) {
|
||||||
|
if (phase == KBBackspaceChunkPhaseWhitespace) {
|
||||||
|
if (currentClass == KBBackspaceChunkClassWhitespace) {
|
||||||
deleteCount += 1;
|
deleteCount += 1;
|
||||||
|
consumed = YES;
|
||||||
|
} else {
|
||||||
|
phase = KBBackspaceChunkPhasePunctuation;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (phase == KBBackspaceChunkPhasePunctuation) {
|
||||||
|
if (currentClass == KBBackspaceChunkClassPunctuation) {
|
||||||
|
deleteCount += 1;
|
||||||
|
consumed = YES;
|
||||||
|
} else {
|
||||||
|
phase = KBBackspaceChunkPhaseCore;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// phase == Core:连续删同一类(ASCII 单词 / 其它),让效果更像微信“几个字一组”
|
||||||
|
if (coreClass == KBBackspaceChunkClassUnknown) {
|
||||||
|
coreClass = currentClass;
|
||||||
|
}
|
||||||
|
if (currentClass != coreClass) {
|
||||||
|
*stop = YES;
|
||||||
|
consumed = YES;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
deleteCount += 1;
|
||||||
|
consumed = YES;
|
||||||
|
}
|
||||||
|
|
||||||
if (deleteCount >= maxCount) {
|
if (deleteCount >= maxCount) {
|
||||||
*stop = YES;
|
*stop = YES;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
|
|
||||||
@@ -480,12 +523,23 @@ typedef NS_ENUM(NSInteger, KBClearPhase) {
|
|||||||
if (!ivc) { return; }
|
if (!ivc) { return; }
|
||||||
id<UITextDocumentProxy> proxy = ivc.textDocumentProxy;
|
id<UITextDocumentProxy> proxy = ivc.textDocumentProxy;
|
||||||
NSInteger nextEmptyRounds = emptyRounds;
|
NSInteger nextEmptyRounds = emptyRounds;
|
||||||
static NSCharacterSet *sentenceBoundarySet = nil;
|
static NSCharacterSet *stopBoundarySet = nil;
|
||||||
static NSCharacterSet *whitespaceSet = nil;
|
static NSCharacterSet *trailingBoundarySet = nil;
|
||||||
|
static NSCharacterSet *trailingWhitespaceSet = nil;
|
||||||
static dispatch_once_t onceToken;
|
static dispatch_once_t onceToken;
|
||||||
dispatch_once(&onceToken, ^{
|
dispatch_once(&onceToken, ^{
|
||||||
sentenceBoundarySet = [NSCharacterSet characterSetWithCharactersInString:@".!?。!?"];
|
// stopBoundary: 遇到这些符号就停(不删除它)
|
||||||
whitespaceSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];
|
// - 句末符号:. ! ? 。!?
|
||||||
|
// - 省略号:…(中文里“……”常用作句/段落的停顿)
|
||||||
|
// - 换行:\n \r(段落边界,避免一次“清空”跨段把全文删完)
|
||||||
|
stopBoundarySet = [NSCharacterSet characterSetWithCharactersInString:@".!?。!?…\n\r\u2028\u2029"];
|
||||||
|
|
||||||
|
// trailingBoundary: 允许作为“尾部句末符号”先删掉,再继续删上一句(更接近微信体验)
|
||||||
|
// 注意:不要把换行/省略号放进来,否则可能跨段/跨停顿继续删。
|
||||||
|
trailingBoundarySet = [NSCharacterSet characterSetWithCharactersInString:@".!?。!?"];
|
||||||
|
|
||||||
|
// trailingWhitespace: 只跳过空格/Tab(不包含换行,换行由 stopBoundarySet 处理)
|
||||||
|
trailingWhitespaceSet = [NSCharacterSet whitespaceCharacterSet];
|
||||||
});
|
});
|
||||||
KBClearPhase phase = self.backspaceClearPhase;
|
KBClearPhase phase = self.backspaceClearPhase;
|
||||||
|
|
||||||
@@ -496,10 +550,9 @@ typedef NS_ENUM(NSInteger, KBClearPhase) {
|
|||||||
NSString *before = proxy.documentContextBeforeInput ?: @"";
|
NSString *before = proxy.documentContextBeforeInput ?: @"";
|
||||||
if (before.length == 0) {
|
if (before.length == 0) {
|
||||||
nextEmptyRounds += 1;
|
nextEmptyRounds += 1;
|
||||||
// 即使 context 为空,也尝试删一次(某些宿主延迟更新)
|
// 宿主(微信/QQ 等)可能在长文本场景下返回空 context,即使还有很多内容。
|
||||||
[[KBBackspaceUndoManager shared] captureAndDeleteBackwardFromProxy:proxy count:1];
|
// 为了避免一次“清空”误删全文:一旦拿不到 before,就立刻停止本次清空。
|
||||||
[[KBInputBufferManager shared] applyClearDeleteCount:1];
|
shouldStop = YES;
|
||||||
deletedThisTick += 1;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
nextEmptyRounds = 0;
|
nextEmptyRounds = 0;
|
||||||
@@ -520,8 +573,9 @@ typedef NS_ENUM(NSInteger, KBClearPhase) {
|
|||||||
}];
|
}];
|
||||||
if (lastChar.length == 0) { break; }
|
if (lastChar.length == 0) { break; }
|
||||||
|
|
||||||
BOOL isWhitespace = ([lastChar rangeOfCharacterFromSet:whitespaceSet].location != NSNotFound);
|
BOOL isWhitespace = ([lastChar rangeOfCharacterFromSet:trailingWhitespaceSet].location != NSNotFound);
|
||||||
BOOL isBoundary = ([lastChar rangeOfCharacterFromSet:sentenceBoundarySet].location != NSNotFound);
|
BOOL isStopBoundary = ([lastChar rangeOfCharacterFromSet:stopBoundarySet].location != NSNotFound);
|
||||||
|
BOOL isTrailingBoundary = ([lastChar rangeOfCharacterFromSet:trailingBoundarySet].location != NSNotFound);
|
||||||
|
|
||||||
if (phase == KBClearPhaseSkipWhitespace) {
|
if (phase == KBClearPhaseSkipWhitespace) {
|
||||||
if (isWhitespace) {
|
if (isWhitespace) {
|
||||||
@@ -534,7 +588,7 @@ typedef NS_ENUM(NSInteger, KBClearPhase) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (phase == KBClearPhaseSkipTrailingBoundary) {
|
if (phase == KBClearPhaseSkipTrailingBoundary) {
|
||||||
if (isBoundary) {
|
if (isTrailingBoundary) {
|
||||||
[[KBBackspaceUndoManager shared] captureAndDeleteBackwardFromProxy:proxy count:1];
|
[[KBBackspaceUndoManager shared] captureAndDeleteBackwardFromProxy:proxy count:1];
|
||||||
[[KBInputBufferManager shared] applyClearDeleteCount:1];
|
[[KBInputBufferManager shared] applyClearDeleteCount:1];
|
||||||
deletedThisTick += 1;
|
deletedThisTick += 1;
|
||||||
@@ -544,7 +598,7 @@ typedef NS_ENUM(NSInteger, KBClearPhase) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// phase == DeleteUntilBoundary
|
// phase == DeleteUntilBoundary
|
||||||
if (isBoundary) {
|
if (isStopBoundary) {
|
||||||
shouldStop = YES; // 保留该句末符号
|
shouldStop = YES; // 保留该句末符号
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user