清理键盘emoji内存高的问题

This commit is contained in:
2026-03-04 15:06:49 +08:00
parent fd5de4f197
commit 5c0cf2b435
6 changed files with 158 additions and 22 deletions

View File

@@ -41,6 +41,9 @@ FOUNDATION_EXPORT NSString * const KBEmojiRecentsDidChangeNotification;
/// 更新当前语言对应的分类标题。 /// 更新当前语言对应的分类标题。
- (void)refreshLocalizedTitles; - (void)refreshLocalizedTitles;
/// 释放大块缓存emoji 分类与索引),下次访问会重新加载。
- (void)purgeLargeCaches;
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END

View File

@@ -195,6 +195,12 @@ static const NSUInteger kKBEmojiRecentsLimit = 32;
} }
} }
- (void)purgeLargeCaches {
self.categoriesInternal = nil;
self.itemLookup = nil;
self.recentValues = nil;
}
- (void)onLocalizationChanged:(__unused NSNotification *)note { - (void)onLocalizationChanged:(__unused NSNotification *)note {
[self refreshLocalizedTitles]; [self refreshLocalizedTitles];
[[NSNotificationCenter defaultCenter] postNotificationName:KBEmojiRecentsDidChangeNotification object:nil]; [[NSNotificationCenter defaultCenter] postNotificationName:KBEmojiRecentsDidChangeNotification object:nil];

View File

@@ -37,15 +37,6 @@
_selectionCounts = [NSMutableDictionary dictionary]; _selectionCounts = [NSMutableDictionary dictionary];
NSArray<NSString *> *defaults = [self.class kb_defaultWords]; NSArray<NSString *> *defaults = [self.class kb_defaultWords];
_priorityWords = [NSSet setWithArray:defaults]; _priorityWords = [NSSet setWithArray:defaults];
_words = [self kb_loadWords];
_traditionalChineseWords = [self kb_loadTraditionalChineseWords];
_simplifiedChineseWords = [self kb_loadSimplifiedChineseWords];
_pinyinToTraditionalMap = [self kb_loadPinyinToTraditionalMap];
_bopomofoToChineseMap = [self kb_loadBopomofoToChineseMap];
_spanishWords = [self kb_loadSpanishWords];
_englishWords = [self kb_loadEnglishWords];
_portugueseWords = [self kb_loadPortugueseWords];
_indonesianWords = [self kb_loadIndonesianWords];
} }
return self; return self;
} }
@@ -190,12 +181,16 @@
} else { } else {
self.engineType = KBSuggestionEngineTypeLatin; self.engineType = KBSuggestionEngineTypeLatin;
} }
[self kb_trimCachesForEngineType:self.engineType];
NSLog(@"[KBSuggestionEngine] Engine type set to: %@", engineTypeString); NSLog(@"[KBSuggestionEngine] Engine type set to: %@", engineTypeString);
} }
#pragma mark - English Suggestions #pragma mark - English Suggestions
- (NSArray<NSString *> *)kb_englishSuggestionsForPrefix:(NSString *)prefix limit:(NSUInteger)limit { - (NSArray<NSString *> *)kb_englishSuggestionsForPrefix:(NSString *)prefix limit:(NSUInteger)limit {
if (!self.englishWords) {
self.englishWords = [self kb_loadEnglishWords];
}
NSArray<NSString *> *matches = [self kb_suggestionsFromWordList:self.englishWords NSArray<NSString *> *matches = [self kb_suggestionsFromWordList:self.englishWords
prefix:prefix prefix:prefix
limit:limit]; limit:limit];
@@ -245,6 +240,9 @@
#pragma mark - Latin Suggestions #pragma mark - Latin Suggestions
- (NSArray<NSString *> *)kb_latinSuggestionsForPrefix:(NSString *)prefix limit:(NSUInteger)limit { - (NSArray<NSString *> *)kb_latinSuggestionsForPrefix:(NSString *)prefix limit:(NSUInteger)limit {
if (!self.words) {
self.words = [self kb_loadWords];
}
NSString *lower = prefix.lowercaseString; NSString *lower = prefix.lowercaseString;
NSMutableArray<NSString *> *matches = [NSMutableArray array]; NSMutableArray<NSString *> *matches = [NSMutableArray array];
@@ -282,6 +280,9 @@
#pragma mark - Traditional Chinese Pinyin Suggestions #pragma mark - Traditional Chinese Pinyin Suggestions
- (NSArray<NSString *> *)kb_traditionalPinyinSuggestionsForPrefix:(NSString *)prefix limit:(NSUInteger)limit { - (NSArray<NSString *> *)kb_traditionalPinyinSuggestionsForPrefix:(NSString *)prefix limit:(NSUInteger)limit {
if (!self.pinyinToTraditionalMap) {
self.pinyinToTraditionalMap = [self kb_loadPinyinToTraditionalMap];
}
NSString *lower = prefix.lowercaseString; NSString *lower = prefix.lowercaseString;
NSMutableArray<NSString *> *matches = [NSMutableArray array]; NSMutableArray<NSString *> *matches = [NSMutableArray array];
@@ -320,6 +321,9 @@
} }
- (NSArray<NSString *> *)kb_fallbackTraditionalSuggestions:(NSString *)prefix limit:(NSUInteger)limit { - (NSArray<NSString *> *)kb_fallbackTraditionalSuggestions:(NSString *)prefix limit:(NSUInteger)limit {
if (!self.traditionalChineseWords) {
self.traditionalChineseWords = [self kb_loadTraditionalChineseWords];
}
NSMutableArray<NSString *> *matches = [NSMutableArray array]; NSMutableArray<NSString *> *matches = [NSMutableArray array];
for (NSString *word in self.traditionalChineseWords) { for (NSString *word in self.traditionalChineseWords) {
[matches addObject:word]; [matches addObject:word];
@@ -333,6 +337,9 @@
#pragma mark - Simplified Chinese Pinyin Suggestions #pragma mark - Simplified Chinese Pinyin Suggestions
- (NSArray<NSString *> *)kb_simplifiedPinyinSuggestionsForPrefix:(NSString *)prefix limit:(NSUInteger)limit { - (NSArray<NSString *> *)kb_simplifiedPinyinSuggestionsForPrefix:(NSString *)prefix limit:(NSUInteger)limit {
if (!self.pinyinToTraditionalMap) {
self.pinyinToTraditionalMap = [self kb_loadPinyinToTraditionalMap];
}
NSString *lower = prefix.lowercaseString; NSString *lower = prefix.lowercaseString;
NSMutableArray<NSString *> *matches = [NSMutableArray array]; NSMutableArray<NSString *> *matches = [NSMutableArray array];
@@ -381,6 +388,9 @@
} }
- (NSArray<NSString *> *)kb_fallbackSimplifiedSuggestions:(NSString *)prefix limit:(NSUInteger)limit { - (NSArray<NSString *> *)kb_fallbackSimplifiedSuggestions:(NSString *)prefix limit:(NSUInteger)limit {
if (!self.simplifiedChineseWords) {
self.simplifiedChineseWords = [self kb_loadSimplifiedChineseWords];
}
NSMutableArray<NSString *> *matches = [NSMutableArray array]; NSMutableArray<NSString *> *matches = [NSMutableArray array];
for (NSString *word in self.simplifiedChineseWords) { for (NSString *word in self.simplifiedChineseWords) {
[matches addObject:word]; [matches addObject:word];
@@ -447,6 +457,9 @@
#pragma mark - Bopomofo (Zhuyin) Suggestions #pragma mark - Bopomofo (Zhuyin) Suggestions
- (NSArray<NSString *> *)kb_bopomofoSuggestionsForPrefix:(NSString *)prefix limit:(NSUInteger)limit { - (NSArray<NSString *> *)kb_bopomofoSuggestionsForPrefix:(NSString *)prefix limit:(NSUInteger)limit {
if (!self.bopomofoToChineseMap) {
self.bopomofoToChineseMap = [self kb_loadBopomofoToChineseMap];
}
NSMutableArray<NSString *> *matches = [NSMutableArray array]; NSMutableArray<NSString *> *matches = [NSMutableArray array];
NSArray<NSString *> *directMatches = self.bopomofoToChineseMap[prefix]; NSArray<NSString *> *directMatches = self.bopomofoToChineseMap[prefix];
@@ -606,6 +619,9 @@
#pragma mark - Spanish Suggestions #pragma mark - Spanish Suggestions
- (NSArray<NSString *> *)kb_spanishSuggestionsForPrefix:(NSString *)prefix limit:(NSUInteger)limit { - (NSArray<NSString *> *)kb_spanishSuggestionsForPrefix:(NSString *)prefix limit:(NSUInteger)limit {
if (!self.spanishWords) {
self.spanishWords = [self kb_loadSpanishWords];
}
NSArray<NSString *> *matches = [self kb_suggestionsFromWordList:self.spanishWords NSArray<NSString *> *matches = [self kb_suggestionsFromWordList:self.spanishWords
prefix:prefix prefix:prefix
limit:limit]; limit:limit];
@@ -655,6 +671,9 @@
#pragma mark - Portuguese Suggestions #pragma mark - Portuguese Suggestions
- (NSArray<NSString *> *)kb_portugueseSuggestionsForPrefix:(NSString *)prefix limit:(NSUInteger)limit { - (NSArray<NSString *> *)kb_portugueseSuggestionsForPrefix:(NSString *)prefix limit:(NSUInteger)limit {
if (!self.portugueseWords) {
self.portugueseWords = [self kb_loadPortugueseWords];
}
NSArray<NSString *> *matches = [self kb_suggestionsFromWordList:self.portugueseWords NSArray<NSString *> *matches = [self kb_suggestionsFromWordList:self.portugueseWords
prefix:prefix prefix:prefix
limit:limit]; limit:limit];
@@ -704,6 +723,9 @@
#pragma mark - Indonesian Suggestions #pragma mark - Indonesian Suggestions
- (NSArray<NSString *> *)kb_indonesianSuggestionsForPrefix:(NSString *)prefix limit:(NSUInteger)limit { - (NSArray<NSString *> *)kb_indonesianSuggestionsForPrefix:(NSString *)prefix limit:(NSUInteger)limit {
if (!self.indonesianWords) {
self.indonesianWords = [self kb_loadIndonesianWords];
}
NSArray<NSString *> *matches = [self kb_suggestionsFromWordList:self.indonesianWords NSArray<NSString *> *matches = [self kb_suggestionsFromWordList:self.indonesianWords
prefix:prefix prefix:prefix
limit:limit]; limit:limit];
@@ -784,4 +806,78 @@
return matches.copy; return matches.copy;
} }
- (void)kb_trimCachesForEngineType:(KBSuggestionEngineType)engineType {
switch (engineType) {
case KBSuggestionEngineTypeEnglish:
self.spanishWords = nil;
self.portugueseWords = nil;
self.indonesianWords = nil;
self.words = nil;
self.traditionalChineseWords = nil;
self.simplifiedChineseWords = nil;
self.pinyinToTraditionalMap = nil;
self.bopomofoToChineseMap = nil;
break;
case KBSuggestionEngineTypeSpanish:
self.englishWords = nil;
self.portugueseWords = nil;
self.indonesianWords = nil;
self.words = nil;
self.traditionalChineseWords = nil;
self.simplifiedChineseWords = nil;
self.pinyinToTraditionalMap = nil;
self.bopomofoToChineseMap = nil;
break;
case KBSuggestionEngineTypePortuguese:
self.englishWords = nil;
self.spanishWords = nil;
self.indonesianWords = nil;
self.words = nil;
self.traditionalChineseWords = nil;
self.simplifiedChineseWords = nil;
self.pinyinToTraditionalMap = nil;
self.bopomofoToChineseMap = nil;
break;
case KBSuggestionEngineTypeIndonesian:
self.englishWords = nil;
self.spanishWords = nil;
self.portugueseWords = nil;
self.words = nil;
self.traditionalChineseWords = nil;
self.simplifiedChineseWords = nil;
self.pinyinToTraditionalMap = nil;
self.bopomofoToChineseMap = nil;
break;
case KBSuggestionEngineTypePinyinTraditional:
case KBSuggestionEngineTypePinyinSimplified:
self.words = nil;
self.englishWords = nil;
self.spanishWords = nil;
self.portugueseWords = nil;
self.indonesianWords = nil;
self.bopomofoToChineseMap = nil;
break;
case KBSuggestionEngineTypeBopomofo:
self.words = nil;
self.englishWords = nil;
self.spanishWords = nil;
self.portugueseWords = nil;
self.indonesianWords = nil;
self.pinyinToTraditionalMap = nil;
self.simplifiedChineseWords = nil;
break;
case KBSuggestionEngineTypeLatin:
default:
self.englishWords = nil;
self.spanishWords = nil;
self.portugueseWords = nil;
self.indonesianWords = nil;
self.traditionalChineseWords = nil;
self.simplifiedChineseWords = nil;
self.pinyinToTraditionalMap = nil;
self.bopomofoToChineseMap = nil;
break;
}
}
@end @end

View File

@@ -30,6 +30,9 @@ NS_ASSUME_NONNULL_BEGIN
/// 高亮指定分类 /// 高亮指定分类
- (void)selectCategoryAtIndex:(NSInteger)index; - (void)selectCategoryAtIndex:(NSInteger)index;
/// 释放 emoji 数据缓存(隐藏面板时可用)
- (void)purgeEmojiCache;
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END

View File

@@ -185,6 +185,15 @@
[self updateSelectionToIndex:preserved]; [self updateSelectionToIndex:preserved];
} }
- (void)purgeEmojiCache {
[self.dataProvider purgeLargeCaches];
self.categories = @[];
self.currentIndex = NSNotFound;
self.titleLabel.text = @"";
[self rebuildTabButtons];
[self.collectionView reloadData];
}
- (void)rebuildTabButtons { - (void)rebuildTabButtons {
UIStackView *stackView = self.bottomBar.tabStackView; UIStackView *stackView = self.bottomBar.tabStackView;
if (!stackView) { return; } if (!stackView) { return; }

View File

@@ -66,14 +66,7 @@
make.bottom.equalTo(self.mas_bottom).offset(-bottomInset); make.bottom.equalTo(self.mas_bottom).offset(-bottomInset);
}]; }];
self.emojiView = [[KBEmojiPanelView alloc] init]; // emoji
self.emojiView.hidden = YES;
self.emojiView.alpha = 0.0;
self.emojiView.delegate = self;
[self addSubview:self.emojiView];
[self.emojiView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self);
}];
// [self.topBar mas_makeConstraints:^(MASConstraintMaker *make) { // [self.topBar mas_makeConstraints:^(MASConstraintMaker *make) {
// make.left.right.equalTo(self); // make.left.right.equalTo(self);
@@ -116,9 +109,10 @@
if (self.emojiPanelVisible == visible) return; if (self.emojiPanelVisible == visible) return;
self.emojiPanelVisible = visible; self.emojiPanelVisible = visible;
if (visible) { if (visible) {
[self.emojiView reloadData]; KBEmojiPanelView *emojiView = [self emojiView];
self.emojiView.hidden = NO; [emojiView reloadData];
[self bringSubviewToFront:self.emojiView]; emojiView.hidden = NO;
[self bringSubviewToFront:emojiView];
} else { } else {
self.keyboardView.hidden = NO; self.keyboardView.hidden = NO;
self.topBar.hidden = NO; self.topBar.hidden = NO;
@@ -126,19 +120,28 @@
} }
void (^changes)(void) = ^{ void (^changes)(void) = ^{
self.emojiView.alpha = visible ? 1.0 : 0.0; if (self.emojiView) {
self.emojiView.alpha = visible ? 1.0 : 0.0;
}
self.keyboardView.alpha = visible ? 0.0 : 1.0; self.keyboardView.alpha = visible ? 0.0 : 1.0;
self.topBar.alpha = visible ? 0.0 : 1.0; self.topBar.alpha = visible ? 0.0 : 1.0;
self.suggestionBar.alpha = visible ? 0.0 : ([self kb_shouldShowSuggestions] ? 1.0 : 0.0); self.suggestionBar.alpha = visible ? 0.0 : ([self kb_shouldShowSuggestions] ? 1.0 : 0.0);
}; };
void (^completion)(BOOL) = ^(BOOL finished) { void (^completion)(BOOL) = ^(BOOL finished) {
self.emojiView.hidden = !visible; if (self.emojiView) {
self.emojiView.hidden = !visible;
}
self.keyboardView.hidden = visible; self.keyboardView.hidden = visible;
self.topBar.hidden = visible; self.topBar.hidden = visible;
if (visible) { if (visible) {
self.suggestionBar.hidden = YES; self.suggestionBar.hidden = YES;
} else { } else {
self.suggestionBar.hidden = ![self kb_shouldShowSuggestions]; self.suggestionBar.hidden = ![self kb_shouldShowSuggestions];
if (self.emojiView) {
[self.emojiView purgeEmojiCache];
[self.emojiView removeFromSuperview];
self.emojiView = nil;
}
} }
}; };
@@ -154,6 +157,22 @@
[self setEmojiPanelVisible:!self.emojiPanelVisible animated:YES]; [self setEmojiPanelVisible:!self.emojiPanelVisible animated:YES];
} }
#pragma mark - Lazy Load
- (KBEmojiPanelView *)emojiView {
if (!_emojiView) {
_emojiView = [[KBEmojiPanelView alloc] init];
_emojiView.hidden = YES;
_emojiView.alpha = 0.0;
_emojiView.delegate = self;
[self addSubview:_emojiView];
[_emojiView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self);
}];
}
return _emojiView;
}
#pragma mark - KBToolBarDelegate #pragma mark - KBToolBarDelegate