diff --git a/CustomKeyboard/Manager/KBEmojiDataProvider.h b/CustomKeyboard/Manager/KBEmojiDataProvider.h index fdae80f..5082b0e 100644 --- a/CustomKeyboard/Manager/KBEmojiDataProvider.h +++ b/CustomKeyboard/Manager/KBEmojiDataProvider.h @@ -41,6 +41,9 @@ FOUNDATION_EXPORT NSString * const KBEmojiRecentsDidChangeNotification; /// 更新当前语言对应的分类标题。 - (void)refreshLocalizedTitles; +/// 释放大块缓存(emoji 分类与索引),下次访问会重新加载。 +- (void)purgeLargeCaches; + @end NS_ASSUME_NONNULL_END diff --git a/CustomKeyboard/Manager/KBEmojiDataProvider.m b/CustomKeyboard/Manager/KBEmojiDataProvider.m index 56f34b9..e660298 100644 --- a/CustomKeyboard/Manager/KBEmojiDataProvider.m +++ b/CustomKeyboard/Manager/KBEmojiDataProvider.m @@ -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 { [self refreshLocalizedTitles]; [[NSNotificationCenter defaultCenter] postNotificationName:KBEmojiRecentsDidChangeNotification object:nil]; diff --git a/CustomKeyboard/Manager/KBSuggestionEngine.m b/CustomKeyboard/Manager/KBSuggestionEngine.m index ece5fcc..d3f1f92 100644 --- a/CustomKeyboard/Manager/KBSuggestionEngine.m +++ b/CustomKeyboard/Manager/KBSuggestionEngine.m @@ -37,15 +37,6 @@ _selectionCounts = [NSMutableDictionary dictionary]; NSArray *defaults = [self.class kb_defaultWords]; _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; } @@ -190,12 +181,16 @@ } else { self.engineType = KBSuggestionEngineTypeLatin; } + [self kb_trimCachesForEngineType:self.engineType]; NSLog(@"[KBSuggestionEngine] Engine type set to: %@", engineTypeString); } #pragma mark - English Suggestions - (NSArray *)kb_englishSuggestionsForPrefix:(NSString *)prefix limit:(NSUInteger)limit { + if (!self.englishWords) { + self.englishWords = [self kb_loadEnglishWords]; + } NSArray *matches = [self kb_suggestionsFromWordList:self.englishWords prefix:prefix limit:limit]; @@ -245,6 +240,9 @@ #pragma mark - Latin Suggestions - (NSArray *)kb_latinSuggestionsForPrefix:(NSString *)prefix limit:(NSUInteger)limit { + if (!self.words) { + self.words = [self kb_loadWords]; + } NSString *lower = prefix.lowercaseString; NSMutableArray *matches = [NSMutableArray array]; @@ -282,6 +280,9 @@ #pragma mark - Traditional Chinese Pinyin Suggestions - (NSArray *)kb_traditionalPinyinSuggestionsForPrefix:(NSString *)prefix limit:(NSUInteger)limit { + if (!self.pinyinToTraditionalMap) { + self.pinyinToTraditionalMap = [self kb_loadPinyinToTraditionalMap]; + } NSString *lower = prefix.lowercaseString; NSMutableArray *matches = [NSMutableArray array]; @@ -320,6 +321,9 @@ } - (NSArray *)kb_fallbackTraditionalSuggestions:(NSString *)prefix limit:(NSUInteger)limit { + if (!self.traditionalChineseWords) { + self.traditionalChineseWords = [self kb_loadTraditionalChineseWords]; + } NSMutableArray *matches = [NSMutableArray array]; for (NSString *word in self.traditionalChineseWords) { [matches addObject:word]; @@ -333,6 +337,9 @@ #pragma mark - Simplified Chinese Pinyin Suggestions - (NSArray *)kb_simplifiedPinyinSuggestionsForPrefix:(NSString *)prefix limit:(NSUInteger)limit { + if (!self.pinyinToTraditionalMap) { + self.pinyinToTraditionalMap = [self kb_loadPinyinToTraditionalMap]; + } NSString *lower = prefix.lowercaseString; NSMutableArray *matches = [NSMutableArray array]; @@ -381,6 +388,9 @@ } - (NSArray *)kb_fallbackSimplifiedSuggestions:(NSString *)prefix limit:(NSUInteger)limit { + if (!self.simplifiedChineseWords) { + self.simplifiedChineseWords = [self kb_loadSimplifiedChineseWords]; + } NSMutableArray *matches = [NSMutableArray array]; for (NSString *word in self.simplifiedChineseWords) { [matches addObject:word]; @@ -447,6 +457,9 @@ #pragma mark - Bopomofo (Zhuyin) Suggestions - (NSArray *)kb_bopomofoSuggestionsForPrefix:(NSString *)prefix limit:(NSUInteger)limit { + if (!self.bopomofoToChineseMap) { + self.bopomofoToChineseMap = [self kb_loadBopomofoToChineseMap]; + } NSMutableArray *matches = [NSMutableArray array]; NSArray *directMatches = self.bopomofoToChineseMap[prefix]; @@ -606,6 +619,9 @@ #pragma mark - Spanish Suggestions - (NSArray *)kb_spanishSuggestionsForPrefix:(NSString *)prefix limit:(NSUInteger)limit { + if (!self.spanishWords) { + self.spanishWords = [self kb_loadSpanishWords]; + } NSArray *matches = [self kb_suggestionsFromWordList:self.spanishWords prefix:prefix limit:limit]; @@ -655,6 +671,9 @@ #pragma mark - Portuguese Suggestions - (NSArray *)kb_portugueseSuggestionsForPrefix:(NSString *)prefix limit:(NSUInteger)limit { + if (!self.portugueseWords) { + self.portugueseWords = [self kb_loadPortugueseWords]; + } NSArray *matches = [self kb_suggestionsFromWordList:self.portugueseWords prefix:prefix limit:limit]; @@ -704,6 +723,9 @@ #pragma mark - Indonesian Suggestions - (NSArray *)kb_indonesianSuggestionsForPrefix:(NSString *)prefix limit:(NSUInteger)limit { + if (!self.indonesianWords) { + self.indonesianWords = [self kb_loadIndonesianWords]; + } NSArray *matches = [self kb_suggestionsFromWordList:self.indonesianWords prefix:prefix limit:limit]; @@ -784,4 +806,78 @@ 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 diff --git a/CustomKeyboard/View/EmojiView/KBEmojiPanelView.h b/CustomKeyboard/View/EmojiView/KBEmojiPanelView.h index d58cd1d..706b367 100644 --- a/CustomKeyboard/View/EmojiView/KBEmojiPanelView.h +++ b/CustomKeyboard/View/EmojiView/KBEmojiPanelView.h @@ -30,6 +30,9 @@ NS_ASSUME_NONNULL_BEGIN /// 高亮指定分类 - (void)selectCategoryAtIndex:(NSInteger)index; +/// 释放 emoji 数据缓存(隐藏面板时可用) +- (void)purgeEmojiCache; + @end NS_ASSUME_NONNULL_END diff --git a/CustomKeyboard/View/EmojiView/KBEmojiPanelView.m b/CustomKeyboard/View/EmojiView/KBEmojiPanelView.m index ecc1117..00a20b7 100644 --- a/CustomKeyboard/View/EmojiView/KBEmojiPanelView.m +++ b/CustomKeyboard/View/EmojiView/KBEmojiPanelView.m @@ -185,6 +185,15 @@ [self updateSelectionToIndex:preserved]; } +- (void)purgeEmojiCache { + [self.dataProvider purgeLargeCaches]; + self.categories = @[]; + self.currentIndex = NSNotFound; + self.titleLabel.text = @""; + [self rebuildTabButtons]; + [self.collectionView reloadData]; +} + - (void)rebuildTabButtons { UIStackView *stackView = self.bottomBar.tabStackView; if (!stackView) { return; } diff --git a/CustomKeyboard/View/KBKeyBoardMainView.m b/CustomKeyboard/View/KBKeyBoardMainView.m index 90b249f..fdef548 100644 --- a/CustomKeyboard/View/KBKeyBoardMainView.m +++ b/CustomKeyboard/View/KBKeyBoardMainView.m @@ -66,14 +66,7 @@ make.bottom.equalTo(self.mas_bottom).offset(-bottomInset); }]; - self.emojiView = [[KBEmojiPanelView alloc] init]; - 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); - }]; + // emoji 面板改为按需创建 // [self.topBar mas_makeConstraints:^(MASConstraintMaker *make) { // make.left.right.equalTo(self); @@ -116,9 +109,10 @@ if (self.emojiPanelVisible == visible) return; self.emojiPanelVisible = visible; if (visible) { - [self.emojiView reloadData]; - self.emojiView.hidden = NO; - [self bringSubviewToFront:self.emojiView]; + KBEmojiPanelView *emojiView = [self emojiView]; + [emojiView reloadData]; + emojiView.hidden = NO; + [self bringSubviewToFront:emojiView]; } else { self.keyboardView.hidden = NO; self.topBar.hidden = NO; @@ -126,19 +120,28 @@ } 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.topBar.alpha = visible ? 0.0 : 1.0; self.suggestionBar.alpha = visible ? 0.0 : ([self kb_shouldShowSuggestions] ? 1.0 : 0.0); }; void (^completion)(BOOL) = ^(BOOL finished) { - self.emojiView.hidden = !visible; + if (self.emojiView) { + self.emojiView.hidden = !visible; + } self.keyboardView.hidden = visible; self.topBar.hidden = visible; if (visible) { self.suggestionBar.hidden = YES; } else { 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]; } +#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