1
This commit is contained in:
@@ -78,10 +78,6 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
KBFunctionView *functionView; // 功能面板视图(点击工具栏第0个时显示)
|
||||
@property(nonatomic, strong) KBSettingView *settingView; // 设置页
|
||||
@property(nonatomic, strong) UIImageView *bgImageView; // 背景图(在底层)
|
||||
@property(nonatomic, strong) UIImageView *personaAvatarImageView; // 语音模式下显示的 persona 小头像
|
||||
@property(nonatomic, strong) UIImageView *personaGrayImageView; // 语音模式下显示的 persona 小头像
|
||||
@property(nonatomic, strong) UIVisualEffectView *personaBlurView; // 语音模式下头像高斯模糊层
|
||||
|
||||
@property(nonatomic, strong) KBChatPanelView *chatPanelView;
|
||||
@property(nonatomic, strong) KBKeyboardSubscriptionView *subscriptionView;
|
||||
@property(nonatomic, strong) KBSuggestionEngine *suggestionEngine;
|
||||
@@ -96,9 +92,13 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
@property(nonatomic, strong) NSLayoutConstraint *kb_widthConstraint;
|
||||
@property(nonatomic, assign) CGFloat kb_lastPortraitWidth;
|
||||
@property(nonatomic, assign) CGFloat kb_lastKeyboardHeight;
|
||||
@property(nonatomic, strong) UIImage *kb_cachedGradientImage;
|
||||
@property(nonatomic, assign) CGSize kb_cachedGradientSize;
|
||||
@property(nonatomic, strong) NSMutableArray<KBChatMessage *> *chatMessages;
|
||||
@property(nonatomic, strong) AVAudioPlayer *chatAudioPlayer;
|
||||
@property(nonatomic, assign) BOOL chatPanelVisible;
|
||||
@property(nonatomic, strong, nullable) id kb_fullAccessObserverToken;
|
||||
@property(nonatomic, strong, nullable) id kb_skinObserverToken;
|
||||
@end
|
||||
|
||||
@implementation KeyboardViewController
|
||||
@@ -118,7 +118,7 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
[KBHUD setContainerView:self.view];
|
||||
// 绑定完全访问管理器,便于统一感知和联动网络开关
|
||||
[[KBFullAccessManager shared] bindInputController:self];
|
||||
__unused id token = [[NSNotificationCenter defaultCenter]
|
||||
self.kb_fullAccessObserverToken = [[NSNotificationCenter defaultCenter]
|
||||
addObserverForName:KBFullAccessChangedNotification
|
||||
object:nil
|
||||
queue:[NSOperationQueue mainQueue]
|
||||
@@ -127,11 +127,16 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
}];
|
||||
|
||||
// 皮肤变化时,立即应用
|
||||
__unused id token2 = [[NSNotificationCenter defaultCenter]
|
||||
__weak typeof(self) weakSelf = self;
|
||||
self.kb_skinObserverToken = [[NSNotificationCenter defaultCenter]
|
||||
addObserverForName:KBSkinDidChangeNotification
|
||||
object:nil
|
||||
queue:[NSOperationQueue mainQueue]
|
||||
usingBlock:^(__unused NSNotification *_Nonnull note) {
|
||||
__strong typeof(weakSelf) self = weakSelf;
|
||||
if (!self) {
|
||||
return;
|
||||
}
|
||||
[self kb_applyTheme];
|
||||
}];
|
||||
[self kb_applyTheme];
|
||||
@@ -162,8 +167,6 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
- (void)viewWillDisappear:(BOOL)animated {
|
||||
[super viewWillDisappear:animated];
|
||||
[[KBBackspaceUndoManager shared] registerNonClearAction];
|
||||
// 清理 persona 头像内存
|
||||
[self kb_hidePersonaAvatar];
|
||||
}
|
||||
|
||||
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
|
||||
@@ -171,6 +174,7 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
if (@available(iOS 13.0, *)) {
|
||||
if (previousTraitCollection.userInterfaceStyle !=
|
||||
self.traitCollection.userInterfaceStyle) {
|
||||
self.kb_cachedGradientImage = nil;
|
||||
[self kb_applyDefaultSkinIfNeeded];
|
||||
}
|
||||
}
|
||||
@@ -250,6 +254,9 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
make.height.mas_equalTo(chatPanelHeight);
|
||||
}];
|
||||
self.chatPanelView.hidden = YES;
|
||||
|
||||
// 初始隐藏,避免布局完成前闪烁
|
||||
self.contentView.hidden = YES;
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
@@ -425,19 +432,18 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
pageId:@"keyboard_settings"
|
||||
extra:nil
|
||||
completion:nil];
|
||||
// if (!self.settingView) {
|
||||
self.settingView = [[KBSettingView alloc] init];
|
||||
self.settingView.hidden = YES;
|
||||
[self.contentView addSubview:self.settingView];
|
||||
[self.settingView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
// 与键盘主视图完全等同的区域,保证高度、宽度一致
|
||||
make.edges.equalTo(self.contentView);
|
||||
}];
|
||||
[self.settingView.backButton addTarget:self
|
||||
action:@selector(onTapSettingsBack)
|
||||
forControlEvents:UIControlEventTouchUpInside];
|
||||
// }
|
||||
[self.contentView bringSubviewToFront:self.settingView];
|
||||
KBSettingView *settingView = self.settingView;
|
||||
if (!settingView.superview) {
|
||||
settingView.hidden = YES;
|
||||
[self.contentView addSubview:settingView];
|
||||
[settingView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.edges.equalTo(self.contentView);
|
||||
}];
|
||||
[settingView.backButton addTarget:self
|
||||
action:@selector(onTapSettingsBack)
|
||||
forControlEvents:UIControlEventTouchUpInside];
|
||||
}
|
||||
[self.contentView bringSubviewToFront:settingView];
|
||||
// 以 keyBoardMainView 的实际宽度为准,避免首次添加时 self.view 宽度尚未计算
|
||||
[self.contentView layoutIfNeeded];
|
||||
CGFloat w = CGRectGetWidth(self.keyBoardMainView.bounds);
|
||||
@@ -447,17 +453,18 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
if (w <= 0) {
|
||||
w = [self kb_portraitWidth];
|
||||
}
|
||||
self.settingView.transform = CGAffineTransformMakeTranslation(w, 0);
|
||||
self.settingView.hidden = NO;
|
||||
settingView.transform = CGAffineTransformMakeTranslation(w, 0);
|
||||
settingView.hidden = NO;
|
||||
[UIView animateWithDuration:0.25
|
||||
delay:0
|
||||
options:UIViewAnimationOptionCurveEaseOut
|
||||
animations:^{
|
||||
self.settingView.transform = CGAffineTransformIdentity;
|
||||
settingView.transform = CGAffineTransformIdentity;
|
||||
}
|
||||
completion:nil];
|
||||
} else {
|
||||
if (!self.settingView || self.settingView.hidden)
|
||||
KBSettingView *settingView = self.settingView;
|
||||
if (!settingView.superview || settingView.hidden)
|
||||
return;
|
||||
CGFloat w = CGRectGetWidth(self.keyBoardMainView.bounds);
|
||||
if (w <= 0) {
|
||||
@@ -470,10 +477,10 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
delay:0
|
||||
options:UIViewAnimationOptionCurveEaseIn
|
||||
animations:^{
|
||||
self.settingView.transform = CGAffineTransformMakeTranslation(w, 0);
|
||||
settingView.transform = CGAffineTransformMakeTranslation(w, 0);
|
||||
}
|
||||
completion:^(BOOL finished) {
|
||||
self.settingView.hidden = YES;
|
||||
settingView.hidden = YES;
|
||||
}];
|
||||
}
|
||||
}
|
||||
@@ -663,8 +670,6 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
if (index == 1) {
|
||||
[self showFunctionPanel:NO];
|
||||
[self showChatPanel:YES];
|
||||
// 显示 persona 头像
|
||||
[self kb_showPersonaAvatarOnBgImageView];
|
||||
return;
|
||||
}
|
||||
[self showFunctionPanel:NO];
|
||||
@@ -832,8 +837,6 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
}
|
||||
self.chatAudioPlayer = nil;
|
||||
[self showChatPanel:NO];
|
||||
// 隐藏 persona 头像
|
||||
[self kb_hidePersonaAvatar];
|
||||
}
|
||||
|
||||
#pragma mark - Chat Helpers
|
||||
@@ -1482,108 +1485,6 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
return _subscriptionView;
|
||||
}
|
||||
|
||||
- (UIImageView *)personaAvatarImageView {
|
||||
if (!_personaAvatarImageView) {
|
||||
_personaAvatarImageView = [[UIImageView alloc] init];
|
||||
_personaAvatarImageView.contentMode = UIViewContentModeScaleAspectFill;
|
||||
_personaAvatarImageView.clipsToBounds = YES;
|
||||
_personaAvatarImageView.hidden = YES;
|
||||
[_personaAvatarImageView addSubview:self.personaBlurView];
|
||||
[self.personaBlurView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.edges.equalTo(_personaAvatarImageView);
|
||||
}];
|
||||
}
|
||||
return _personaAvatarImageView;
|
||||
}
|
||||
- (UIImageView *)personaGrayImageView{
|
||||
if (!_personaGrayImageView) {
|
||||
_personaGrayImageView = [[UIImageView alloc] init];
|
||||
_personaAvatarImageView.contentMode = UIViewContentModeScaleAspectFill;
|
||||
|
||||
}
|
||||
return _personaGrayImageView;
|
||||
}
|
||||
|
||||
- (UIVisualEffectView *)personaBlurView {
|
||||
if (!_personaBlurView) {
|
||||
UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
|
||||
_personaBlurView = [[UIVisualEffectView alloc] initWithEffect:effect];
|
||||
_personaBlurView.hidden = YES;
|
||||
_personaBlurView.userInteractionEnabled = NO;
|
||||
}
|
||||
return _personaBlurView;
|
||||
}
|
||||
|
||||
#pragma mark - Persona Avatar
|
||||
|
||||
/// 从 AppGroup 读取选中的 persona 信息
|
||||
- (NSDictionary *)kb_selectedPersonaFromAppGroup {
|
||||
NSUserDefaults *ud = [[NSUserDefaults alloc] initWithSuiteName:AppGroup];
|
||||
NSDictionary *personaDict = [ud objectForKey:@"AppGroup_SelectedPersona"];
|
||||
if ([personaDict isKindOfClass:[NSDictionary class]]) {
|
||||
return personaDict;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
/// 在 bgImageView 上显示 persona 头像
|
||||
- (void)kb_showPersonaAvatarOnBgImageView {
|
||||
// 检查是否有完全访问权限
|
||||
if (![[KBFullAccessManager shared] hasFullAccess]) {
|
||||
NSLog(@"[Keyboard] 未开启完全访问,无法显示 persona 头像");
|
||||
return;
|
||||
}
|
||||
|
||||
// 从 AppGroup 共享目录读取预处理好的小图片
|
||||
NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:AppGroup];
|
||||
if (!containerURL) {
|
||||
NSLog(@"[Keyboard] 无法获取 AppGroup 容器目录");
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *imagePath = [[containerURL path] stringByAppendingPathComponent:@"persona_cover.jpg"];
|
||||
if (![[NSFileManager defaultManager] fileExistsAtPath:imagePath]) {
|
||||
NSLog(@"[Keyboard] persona 封面图文件不存在: %@", imagePath);
|
||||
return;
|
||||
}
|
||||
|
||||
NSLog(@"[Keyboard] 准备从本地加载 persona 封面图: %@", imagePath);
|
||||
|
||||
// 添加视图到 contentView,与 bgImageView 尺寸一致
|
||||
if (!self.personaAvatarImageView.superview) {
|
||||
[self.contentView insertSubview:self.personaAvatarImageView aboveSubview:self.bgImageView];
|
||||
[self.personaAvatarImageView addSubview:self.personaGrayImageView];
|
||||
[self.personaAvatarImageView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.edges.equalTo(self.bgImageView);
|
||||
}];
|
||||
[self.personaGrayImageView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.right.bottom.equalTo(self.personaAvatarImageView);
|
||||
make.height.mas_equalTo(self.keyBoardMainView);
|
||||
}];
|
||||
}
|
||||
|
||||
// 先清理旧图片
|
||||
self.personaAvatarImageView.image = nil;
|
||||
|
||||
// 从本地文件加载图片(已经是缩小后的小图片,内存占用很小)
|
||||
UIImage *image = [UIImage imageWithContentsOfFile:imagePath];
|
||||
if (image) {
|
||||
self.personaAvatarImageView.image = image;
|
||||
self.personaAvatarImageView.hidden = NO;
|
||||
self.personaBlurView.hidden = NO;
|
||||
NSLog(@"[Keyboard] persona 封面图加载成功");
|
||||
} else {
|
||||
NSLog(@"[Keyboard] persona 封面图加载失败");
|
||||
}
|
||||
}
|
||||
|
||||
/// 隐藏 persona 头像
|
||||
- (void)kb_hidePersonaAvatar {
|
||||
self.personaAvatarImageView.hidden = YES;
|
||||
self.personaAvatarImageView.image = nil;
|
||||
self.personaBlurView.hidden = YES;
|
||||
}
|
||||
|
||||
#pragma mark - Actions
|
||||
|
||||
- (void)kb_openRechargeForProduct:(KBKeyboardSubscriptionProduct *)product {
|
||||
@@ -1638,10 +1539,22 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
if (self.kb_fullAccessObserverToken) {
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
removeObserver:self.kb_fullAccessObserverToken];
|
||||
self.kb_fullAccessObserverToken = nil;
|
||||
}
|
||||
if (self.kb_skinObserverToken) {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self.kb_skinObserverToken];
|
||||
self.kb_skinObserverToken = nil;
|
||||
}
|
||||
CFNotificationCenterRemoveObserver(
|
||||
CFNotificationCenterGetDarwinNotifyCenter(),
|
||||
(__bridge const void *)(self),
|
||||
(__bridge CFStringRef)KBDarwinSkinInstallRequestNotification, NULL);
|
||||
#if DEBUG
|
||||
NSLog(@"[Keyboard] KeyboardViewController dealloc");
|
||||
#endif
|
||||
}
|
||||
|
||||
// 当键盘第一次显示时,尝试唤起主 App 以提示登录(由主 App
|
||||
@@ -1659,7 +1572,12 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
|
||||
- (void)viewDidLayoutSubviews {
|
||||
[super viewDidLayoutSubviews];
|
||||
[self kb_updateKeyboardLayoutIfNeeded];
|
||||
// [self kb_updateKeyboardLayoutIfNeeded];
|
||||
|
||||
// 首次布局完成后显示,避免闪烁
|
||||
if (self.contentView.hidden) {
|
||||
self.contentView.hidden = NO;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)viewWillTransitionToSize:(CGSize)size
|
||||
@@ -1749,9 +1667,9 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
}
|
||||
UIColor *topColor = [UIColor colorWithHex:0xDEDFE4];
|
||||
UIColor *bottomColor = [UIColor colorWithHex:0xD1D3DB];
|
||||
img = [self kb_defaultGradientImageWithSize:size
|
||||
topColor:topColor
|
||||
bottomColor:bottomColor];
|
||||
// img = [self kb_defaultGradientImageWithSize:size
|
||||
// topColor:topColor
|
||||
// bottomColor:bottomColor];
|
||||
self.contentView.backgroundColor = [UIColor clearColor];
|
||||
self.bgImageView.backgroundColor = [UIColor clearColor];
|
||||
}
|
||||
@@ -1764,7 +1682,6 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
NSLog(@"⌨️[Keyboard] apply theme id=%@ hasBg=%d", t.skinId, (img != nil));
|
||||
[self kb_logSkinDiagnosticsWithTheme:t backgroundImage:img];
|
||||
self.bgImageView.image = img;
|
||||
self.personaGrayImageView.image = img;
|
||||
|
||||
// [self.chatPanelView kb_setBackgroundImage:img];
|
||||
BOOL hasImg = (img != nil);
|
||||
@@ -1819,8 +1736,12 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
return nil;
|
||||
}
|
||||
|
||||
// 将动态颜色解析为当前 trait collection 下的具体颜色值
|
||||
// 否则在 UIGraphicsBeginImageContextWithOptions 中渲染时会使用默认的浅色模式
|
||||
// 尺寸未变则复用缓存,避免反复创建图片撑爆键盘扩展内存
|
||||
if (self.kb_cachedGradientImage &&
|
||||
CGSizeEqualToSize(self.kb_cachedGradientSize, size)) {
|
||||
return self.kb_cachedGradientImage;
|
||||
}
|
||||
|
||||
UIColor *resolvedTopColor = topColor;
|
||||
UIColor *resolvedBottomColor = bottomColor;
|
||||
if (@available(iOS 13.0, *)) {
|
||||
@@ -1841,6 +1762,9 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
[layer renderInContext:UIGraphicsGetCurrentContext()];
|
||||
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
|
||||
self.kb_cachedGradientImage = image;
|
||||
self.kb_cachedGradientSize = size;
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
@@ -78,7 +78,6 @@
|
||||
046131142ECF454500A6FADF /* KBKeyPreviewView.m in Sources */ = {isa = PBXBuildFile; fileRef = 046131132ECF454500A6FADF /* KBKeyPreviewView.m */; };
|
||||
0477BDF02EBB76E30055D639 /* HomeSheetVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 0477BDEF2EBB76E30055D639 /* HomeSheetVC.m */; };
|
||||
0477BDF32EBB7B850055D639 /* KBDirectionIndicatorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0477BDF22EBB7B850055D639 /* KBDirectionIndicatorView.m */; };
|
||||
0477BDF72EBC63A80055D639 /* KBTestVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 0477BDF62EBC63A80055D639 /* KBTestVC.m */; };
|
||||
0477BDFA2EBC66340055D639 /* HomeHeadView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0477BDF92EBC66340055D639 /* HomeHeadView.m */; };
|
||||
0477BDFD2EBC6A170055D639 /* HomeHotVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 0477BDFC2EBC6A170055D639 /* HomeHotVC.m */; };
|
||||
0477BE002EBC6A330055D639 /* HomeRankVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 0477BDFF2EBC6A330055D639 /* HomeRankVC.m */; };
|
||||
@@ -140,14 +139,13 @@
|
||||
048FFD112F27432D005D62AE /* KBPersonaPageModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD0F2F27432D005D62AE /* KBPersonaPageModel.m */; };
|
||||
048FFD142F274342005D62AE /* KBPersonaChatCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD132F274342005D62AE /* KBPersonaChatCell.m */; };
|
||||
048FFD182F2763A5005D62AE /* KBVoiceInputBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD172F2763A5005D62AE /* KBVoiceInputBar.m */; };
|
||||
048FFD1D2F277486005D62AE /* KBChatHistoryPageModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD1C2F277486005D62AE /* KBChatHistoryPageModel.m */; };
|
||||
048FFD1E2F277486005D62AE /* KBChatHistoryModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD1A2F277486005D62AE /* KBChatHistoryModel.m */; };
|
||||
048FFD242F28A836005D62AE /* KBChatLimitPopView.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD232F28A836005D62AE /* KBChatLimitPopView.m */; };
|
||||
A1B2C9302FCA000100000001 /* KBChatLimitPopView.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD232F28A836005D62AE /* KBChatLimitPopView.m */; };
|
||||
048FFD272F28C6CF005D62AE /* KBImagePositionButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD262F28C6CF005D62AE /* KBImagePositionButton.m */; };
|
||||
048FFD2A2F28E99A005D62AE /* KBCommentModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD292F28E99A005D62AE /* KBCommentModel.m */; };
|
||||
048FFD2D2F29F356005D62AE /* KBAIMessageVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD2C2F29F356005D62AE /* KBAIMessageVC.m */; };
|
||||
048FFD302F29F3C3005D62AE /* KBAIMessageZanVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD2F2F29F3C3005D62AE /* KBAIMessageZanVC.m */; };
|
||||
048FFD1D2F277486005D62AE /* KBChatHistoryPageModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD1C2F277486005D62AE /* KBChatHistoryPageModel.m */; };
|
||||
048FFD1E2F277486005D62AE /* KBChatHistoryModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD1A2F277486005D62AE /* KBChatHistoryModel.m */; };
|
||||
048FFD242F28A836005D62AE /* KBChatLimitPopView.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD232F28A836005D62AE /* KBChatLimitPopView.m */; };
|
||||
048FFD272F28C6CF005D62AE /* KBImagePositionButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD262F28C6CF005D62AE /* KBImagePositionButton.m */; };
|
||||
048FFD2A2F28E99A005D62AE /* KBCommentModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD292F28E99A005D62AE /* KBCommentModel.m */; };
|
||||
048FFD2D2F29F356005D62AE /* KBAIMessageVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD2C2F29F356005D62AE /* KBAIMessageVC.m */; };
|
||||
048FFD302F29F3C3005D62AE /* KBAIMessageZanVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD2F2F29F3C3005D62AE /* KBAIMessageZanVC.m */; };
|
||||
048FFD332F29F3D2005D62AE /* KBAIMessageChatingVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD322F29F3D2005D62AE /* KBAIMessageChatingVC.m */; };
|
||||
048FFD342F29F400005D62AE /* KBAIMessageListVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD362F29F400005D62AE /* KBAIMessageListVC.m */; };
|
||||
048FFD362F29F88E005D62AE /* AIMessageVM.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD352F29F88E005D62AE /* AIMessageVM.m */; };
|
||||
@@ -209,6 +207,8 @@
|
||||
04A9FE202EB893F10020DB6D /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 04A9FE1E2EB893F10020DB6D /* Localizable.strings */; };
|
||||
04A9FE212EB893F10020DB6D /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 04A9FE1E2EB893F10020DB6D /* Localizable.strings */; };
|
||||
04B5A1A22EEFA12300AAAAAA /* KBPayProductModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 04B5A1A12EEFA12300AAAAAA /* KBPayProductModel.m */; };
|
||||
04BBF89D2F3ACD8800B1FBB2 /* KBKeyboardStressTestVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 04BBF89A2F3ACD8800B1FBB2 /* KBKeyboardStressTestVC.m */; };
|
||||
04BBF89E2F3ACD8800B1FBB2 /* KBTestVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 04BBF89C2F3ACD8800B1FBB2 /* KBTestVC.m */; };
|
||||
04C6EABA2EAF86530089C901 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 04C6EAAE2EAF86530089C901 /* Assets.xcassets */; };
|
||||
04C6EABC2EAF86530089C901 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 04C6EAB12EAF86530089C901 /* LaunchScreen.storyboard */; };
|
||||
04C6EABD2EAF86530089C901 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 04C6EAB42EAF86530089C901 /* Main.storyboard */; };
|
||||
@@ -302,6 +302,7 @@
|
||||
A1B2C9262FC9000100000001 /* KBChatMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C9212FC9000100000001 /* KBChatMessage.m */; };
|
||||
A1B2C9272FC9000100000001 /* KBChatMessageCell.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C9232FC9000100000001 /* KBChatMessageCell.m */; };
|
||||
A1B2C9282FC9000100000001 /* KBChatPanelView.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C9252FC9000100000001 /* KBChatPanelView.m */; };
|
||||
A1B2C9302FCA000100000001 /* KBChatLimitPopView.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD232F28A836005D62AE /* KBChatLimitPopView.m */; };
|
||||
A1B2D7022EB8C00100000001 /* KBLangTestVC.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2D7012EB8C00100000001 /* KBLangTestVC.m */; };
|
||||
A1B2E1012EBC7AAA00000001 /* KBTopThreeView.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2E0022EBC7AAA00000001 /* KBTopThreeView.m */; };
|
||||
A1B2E1022EBC7AAA00000001 /* HomeHotCell.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2E0042EBC7AAA00000001 /* HomeHotCell.m */; };
|
||||
@@ -450,8 +451,6 @@
|
||||
0477BDEF2EBB76E30055D639 /* HomeSheetVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HomeSheetVC.m; sourceTree = "<group>"; };
|
||||
0477BDF12EBB7B850055D639 /* KBDirectionIndicatorView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBDirectionIndicatorView.h; sourceTree = "<group>"; };
|
||||
0477BDF22EBB7B850055D639 /* KBDirectionIndicatorView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBDirectionIndicatorView.m; sourceTree = "<group>"; };
|
||||
0477BDF52EBC63A80055D639 /* KBTestVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBTestVC.h; sourceTree = "<group>"; };
|
||||
0477BDF62EBC63A80055D639 /* KBTestVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBTestVC.m; sourceTree = "<group>"; };
|
||||
0477BDF82EBC66340055D639 /* HomeHeadView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeHeadView.h; sourceTree = "<group>"; };
|
||||
0477BDF92EBC66340055D639 /* HomeHeadView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HomeHeadView.m; sourceTree = "<group>"; };
|
||||
0477BDFB2EBC6A170055D639 /* HomeHotVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeHotVC.h; sourceTree = "<group>"; };
|
||||
@@ -685,6 +684,10 @@
|
||||
04A9FE1D2EB893F10020DB6D /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
||||
04B5A1A02EEFA12300AAAAAA /* KBPayProductModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBPayProductModel.h; sourceTree = "<group>"; };
|
||||
04B5A1A12EEFA12300AAAAAA /* KBPayProductModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBPayProductModel.m; sourceTree = "<group>"; };
|
||||
04BBF8992F3ACD8800B1FBB2 /* KBKeyboardStressTestVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBKeyboardStressTestVC.h; sourceTree = "<group>"; };
|
||||
04BBF89A2F3ACD8800B1FBB2 /* KBKeyboardStressTestVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBKeyboardStressTestVC.m; sourceTree = "<group>"; };
|
||||
04BBF89B2F3ACD8800B1FBB2 /* KBTestVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBTestVC.h; sourceTree = "<group>"; };
|
||||
04BBF89C2F3ACD8800B1FBB2 /* KBTestVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBTestVC.m; sourceTree = "<group>"; };
|
||||
04C6EAAC2EAF86530089C901 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
||||
04C6EAAD2EAF86530089C901 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
||||
04C6EAAE2EAF86530089C901 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
@@ -1247,12 +1250,14 @@
|
||||
0477BE012EBC6D420055D639 /* FunctionTest */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0477BDF52EBC63A80055D639 /* KBTestVC.h */,
|
||||
0477BDF62EBC63A80055D639 /* KBTestVC.m */,
|
||||
A1B2D7002EB8C00100000001 /* KBLangTestVC.h */,
|
||||
A1B2D7012EB8C00100000001 /* KBLangTestVC.m */,
|
||||
0459D1B22EBA284C00F2D189 /* KBSkinCenterVC.h */,
|
||||
0459D1B32EBA284C00F2D189 /* KBSkinCenterVC.m */,
|
||||
04BBF8992F3ACD8800B1FBB2 /* KBKeyboardStressTestVC.h */,
|
||||
04BBF89A2F3ACD8800B1FBB2 /* KBKeyboardStressTestVC.m */,
|
||||
04BBF89B2F3ACD8800B1FBB2 /* KBTestVC.h */,
|
||||
04BBF89C2F3ACD8800B1FBB2 /* KBTestVC.m */,
|
||||
);
|
||||
path = FunctionTest;
|
||||
sourceTree = "<group>";
|
||||
@@ -2386,15 +2391,15 @@
|
||||
0498BD862EE1BEC9006CC1D5 /* KBSignUtils.m in Sources */,
|
||||
04791FFC2ED71D17004E8522 /* UIColor+Extension.m in Sources */,
|
||||
0450AC4A2EF2C3ED00B6AF06 /* KBKeyboardSubscriptionOptionCell.m in Sources */,
|
||||
04A9FE0F2EB481100020DB6D /* KBHUD.m in Sources */,
|
||||
048FFD562F2B9C3D005D62AE /* KBChatAssistantCell.m in Sources */,
|
||||
048FFD572F2B9C3D005D62AE /* KBChatUserCell.m in Sources */,
|
||||
A1B2C9302FCA000100000001 /* KBChatLimitPopView.m in Sources */,
|
||||
04C6EADD2EAF8CEB0089C901 /* KBToolBar.m in Sources */,
|
||||
A1B2C9262FC9000100000001 /* KBChatMessage.m in Sources */,
|
||||
A1B2C9272FC9000100000001 /* KBChatMessageCell.m in Sources */,
|
||||
A1B2C9282FC9000100000001 /* KBChatPanelView.m in Sources */,
|
||||
A1B2C3EB2F20000000000001 /* KBSuggestionBarView.m in Sources */,
|
||||
04A9FE0F2EB481100020DB6D /* KBHUD.m in Sources */,
|
||||
048FFD562F2B9C3D005D62AE /* KBChatAssistantCell.m in Sources */,
|
||||
048FFD572F2B9C3D005D62AE /* KBChatUserCell.m in Sources */,
|
||||
A1B2C9302FCA000100000001 /* KBChatLimitPopView.m in Sources */,
|
||||
04C6EADD2EAF8CEB0089C901 /* KBToolBar.m in Sources */,
|
||||
A1B2C9262FC9000100000001 /* KBChatMessage.m in Sources */,
|
||||
A1B2C9272FC9000100000001 /* KBChatMessageCell.m in Sources */,
|
||||
A1B2C9282FC9000100000001 /* KBChatPanelView.m in Sources */,
|
||||
A1B2C3EB2F20000000000001 /* KBSuggestionBarView.m in Sources */,
|
||||
0419C9662F2C7693002E86D3 /* KBVM.m in Sources */,
|
||||
048FFD512F2B68F7005D62AE /* KBPersonaModel.m in Sources */,
|
||||
04FC95792EB09BC8007BD342 /* KBKeyBoardMainView.m in Sources */,
|
||||
@@ -2550,7 +2555,6 @@
|
||||
048908D22EBF611D00FABA60 /* KBHistoryMoreCell.m in Sources */,
|
||||
04FC95D82EB1EA16007BD342 /* BaseCell.m in Sources */,
|
||||
0498BD852EE1B255006CC1D5 /* KBSignUtils.m in Sources */,
|
||||
0477BDF72EBC63A80055D639 /* KBTestVC.m in Sources */,
|
||||
04122F7E2EC5FC5500EF7AB3 /* KBJfPayCell.m in Sources */,
|
||||
048FFD502F2B52E7005D62AE /* AIReportVC.m in Sources */,
|
||||
049FB2402EC4B6EF00FAB05D /* KBULBridgeNotification.m in Sources */,
|
||||
@@ -2652,6 +2656,8 @@
|
||||
A1B2E1012EBC7AAA00000001 /* KBTopThreeView.m in Sources */,
|
||||
A1B2E1022EBC7AAA00000001 /* HomeHotCell.m in Sources */,
|
||||
048FFD272F28C6CF005D62AE /* KBImagePositionButton.m in Sources */,
|
||||
04BBF89D2F3ACD8800B1FBB2 /* KBKeyboardStressTestVC.m in Sources */,
|
||||
04BBF89E2F3ACD8800B1FBB2 /* KBTestVC.m in Sources */,
|
||||
0459D1B72EBA287900F2D189 /* KBSkinManager.m in Sources */,
|
||||
04286A002ECAEF2B00CE730C /* KBMoneyBtn.m in Sources */,
|
||||
048908F52EC0496400FABA60 /* KBShopItemVC.m in Sources */,
|
||||
|
||||
@@ -57,8 +57,12 @@
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES"
|
||||
launchAutomaticallySubstyle = "2">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<RemoteRunnable
|
||||
runnableDebuggingMode = "0"
|
||||
BundleIdentifier = "com.loveKey.nyx"
|
||||
RemotePath = "/var/containers/Bundle/Application/E51DCFA2-A182-4B31-8A45-BCCF663ADCAA/keyBoard.app">
|
||||
</RemoteRunnable>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "727EC7522EAF848B00B36487"
|
||||
@@ -66,7 +70,14 @@
|
||||
BlueprintName = "keyBoard"
|
||||
ReferencedContainer = "container:keyBoard.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</MacroExpansion>
|
||||
<EnvironmentVariables>
|
||||
<EnvironmentVariable
|
||||
key = "OS_ACTIVITY_MODE"
|
||||
value = "disable"
|
||||
isEnabled = "NO">
|
||||
</EnvironmentVariable>
|
||||
</EnvironmentVariables>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
|
||||
@@ -480,10 +480,10 @@ static NSString * const KBAISelectedPersonaIdKey = @"KBAISelectedPersonaId";
|
||||
[ud setObject:personaDict forKey:@"AppGroup_SelectedPersona"];
|
||||
[ud synchronize];
|
||||
|
||||
NSLog(@"[KBAIHomeVC] 已保存选中的 persona 到 AppGroup: %@, coverImageUrl: %@", persona.name, persona.coverImageUrl);
|
||||
|
||||
NSLog(@"[KBAIHomeVC] 已保存选中的 persona 到 AppGroup: %@, avatarUrl: %@", persona.name, persona.avatarUrl);
|
||||
|
||||
// 异步下载并缩小图片,保存到 AppGroup 共享目录
|
||||
[self downloadAndSavePersonaCoverImage:persona.coverImageUrl];
|
||||
[self downloadAndSavePersonaCoverImage:persona.avatarUrl];
|
||||
}
|
||||
|
||||
/// 下载并缩小 persona 封面图,保存到 AppGroup 共享目录
|
||||
@@ -511,18 +511,17 @@ static NSString * const KBAISelectedPersonaIdKey = @"KBAISelectedPersonaId";
|
||||
return;
|
||||
}
|
||||
|
||||
// 缩小图片到适合键盘扩展的尺寸(宽度 390,高度按比例)
|
||||
CGFloat targetWidth = 390.0;
|
||||
CGFloat scale = targetWidth / image.size.width;
|
||||
CGSize targetSize = CGSizeMake(targetWidth, image.size.height * scale);
|
||||
|
||||
UIGraphicsBeginImageContextWithOptions(targetSize, YES, 1.0);
|
||||
// 缩小图片到 40x40(仅用于工具栏头像显示)
|
||||
CGFloat targetSide = 40.0;
|
||||
CGSize targetSize = CGSizeMake(targetSide, targetSide);
|
||||
|
||||
UIGraphicsBeginImageContextWithOptions(targetSize, NO, 1.0);
|
||||
[image drawInRect:CGRectMake(0, 0, targetSize.width, targetSize.height)];
|
||||
UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
|
||||
// 压缩为 JPEG,质量 0.6
|
||||
NSData *jpegData = UIImageJPEGRepresentation(scaledImage, 0.6);
|
||||
|
||||
// 压缩为 JPEG,质量 0.8
|
||||
NSData *jpegData = UIImageJPEGRepresentation(scaledImage, 0.8);
|
||||
if (!jpegData) {
|
||||
NSLog(@"[KBAIHomeVC] 压缩图片失败");
|
||||
return;
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface KBKeyboardStressTestVC : BaseViewController
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
142
keyBoard/Class/Home/VC/FunctionTest/KBKeyboardStressTestVC.m
Normal file
142
keyBoard/Class/Home/VC/FunctionTest/KBKeyboardStressTestVC.m
Normal file
@@ -0,0 +1,142 @@
|
||||
#import "KBKeyboardStressTestVC.h"
|
||||
|
||||
@interface KBKeyboardStressTestVC ()
|
||||
@property(nonatomic, strong) UITextView *textView;
|
||||
@property(nonatomic, strong) UIButton *startButton;
|
||||
@property(nonatomic, strong) UIButton *stopButton;
|
||||
@property(nonatomic, strong) UILabel *statusLabel;
|
||||
@property(nonatomic, assign) NSInteger currentCycle;
|
||||
@property(nonatomic, assign) NSInteger totalCycles;
|
||||
@property(nonatomic, assign) BOOL running;
|
||||
@end
|
||||
|
||||
@implementation KBKeyboardStressTestVC
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
self.view.backgroundColor = UIColor.whiteColor;
|
||||
self.title = @"键盘压力测试";
|
||||
self.totalCycles = 200;
|
||||
[self buildUI];
|
||||
[self updateStatus];
|
||||
}
|
||||
|
||||
- (void)viewWillDisappear:(BOOL)animated {
|
||||
[super viewWillDisappear:animated];
|
||||
[self stop];
|
||||
}
|
||||
|
||||
- (void)buildUI {
|
||||
CGFloat w = UIScreen.mainScreen.bounds.size.width;
|
||||
|
||||
self.statusLabel = [[UILabel alloc] initWithFrame:CGRectMake(16, KB_NAV_TOTAL_HEIGHT + 16, w - 32, 22)];
|
||||
self.statusLabel.font = [UIFont systemFontOfSize:13];
|
||||
self.statusLabel.textColor = [UIColor colorWithWhite:0.2 alpha:1];
|
||||
[self.view addSubview:self.statusLabel];
|
||||
|
||||
self.textView = [[UITextView alloc] initWithFrame:CGRectMake(16, CGRectGetMaxY(self.statusLabel.frame) + 12, w - 32, 160)];
|
||||
self.textView.text = @"把系统输入法切到自定义键盘后,点击开始,会反复显示/隐藏键盘。";
|
||||
self.textView.layer.borderColor = [UIColor colorWithWhite:0 alpha:0.15].CGColor;
|
||||
self.textView.layer.borderWidth = 0.5;
|
||||
self.textView.layer.cornerRadius = 8;
|
||||
[self.view addSubview:self.textView];
|
||||
|
||||
CGFloat btnW = (w - 16 * 2 - 12) / 2.0;
|
||||
self.startButton = [UIButton buttonWithType:UIButtonTypeSystem];
|
||||
self.startButton.frame = CGRectMake(16, CGRectGetMaxY(self.textView.frame) + 16, btnW, 44);
|
||||
self.startButton.layer.cornerRadius = 10;
|
||||
self.startButton.backgroundColor = [UIColor colorWithRed:0.22 green:0.49 blue:0.96 alpha:1];
|
||||
[self.startButton setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];
|
||||
[self.startButton setTitle:@"开始" forState:UIControlStateNormal];
|
||||
[self.startButton addTarget:self action:@selector(onStart) forControlEvents:UIControlEventTouchUpInside];
|
||||
[self.view addSubview:self.startButton];
|
||||
|
||||
self.stopButton = [UIButton buttonWithType:UIButtonTypeSystem];
|
||||
self.stopButton.frame = CGRectMake(CGRectGetMaxX(self.startButton.frame) + 12, CGRectGetMinY(self.startButton.frame), btnW, 44);
|
||||
self.stopButton.layer.cornerRadius = 10;
|
||||
self.stopButton.backgroundColor = [UIColor colorWithWhite:0.2 alpha:0.08];
|
||||
[self.stopButton setTitleColor:[UIColor colorWithWhite:0.15 alpha:1] forState:UIControlStateNormal];
|
||||
[self.stopButton setTitle:@"停止" forState:UIControlStateNormal];
|
||||
[self.stopButton addTarget:self action:@selector(onStop) forControlEvents:UIControlEventTouchUpInside];
|
||||
[self.view addSubview:self.stopButton];
|
||||
|
||||
UIButton *oneCycleBtn = [UIButton buttonWithType:UIButtonTypeSystem];
|
||||
oneCycleBtn.frame = CGRectMake(16, CGRectGetMaxY(self.startButton.frame) + 12, w - 32, 44);
|
||||
oneCycleBtn.layer.cornerRadius = 10;
|
||||
oneCycleBtn.backgroundColor = [UIColor colorWithWhite:0.2 alpha:0.08];
|
||||
[oneCycleBtn setTitleColor:[UIColor colorWithWhite:0.15 alpha:1] forState:UIControlStateNormal];
|
||||
[oneCycleBtn setTitle:@"执行 10 次" forState:UIControlStateNormal];
|
||||
[oneCycleBtn addTarget:self action:@selector(onRunTen) forControlEvents:UIControlEventTouchUpInside];
|
||||
[self.view addSubview:oneCycleBtn];
|
||||
}
|
||||
|
||||
- (void)onStart {
|
||||
self.totalCycles = 200;
|
||||
[self start];
|
||||
}
|
||||
|
||||
- (void)onRunTen {
|
||||
self.totalCycles = 10;
|
||||
[self start];
|
||||
}
|
||||
|
||||
- (void)onStop {
|
||||
[self stop];
|
||||
}
|
||||
|
||||
- (void)start {
|
||||
if (self.running) {
|
||||
return;
|
||||
}
|
||||
self.running = YES;
|
||||
self.currentCycle = 0;
|
||||
[self updateStatus];
|
||||
[self runNextCycle];
|
||||
}
|
||||
|
||||
- (void)stop {
|
||||
self.running = NO;
|
||||
[self.textView resignFirstResponder];
|
||||
[self updateStatus];
|
||||
}
|
||||
|
||||
- (void)runNextCycle {
|
||||
if (!self.running) {
|
||||
return;
|
||||
}
|
||||
if (self.currentCycle >= self.totalCycles) {
|
||||
[self stop];
|
||||
return;
|
||||
}
|
||||
|
||||
self.currentCycle += 1;
|
||||
[self updateStatus];
|
||||
|
||||
__weak typeof(self) weakSelf = self;
|
||||
[self.textView becomeFirstResponder];
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.18 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
__strong typeof(weakSelf) self = weakSelf;
|
||||
if (!self || !self.running) {
|
||||
return;
|
||||
}
|
||||
[self.textView resignFirstResponder];
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.12 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
__strong typeof(weakSelf) self = weakSelf;
|
||||
if (!self) {
|
||||
return;
|
||||
}
|
||||
[self runNextCycle];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
- (void)updateStatus {
|
||||
NSString *run = self.running ? @"运行中" : @"未运行";
|
||||
self.statusLabel.text = [NSString stringWithFormat:@"状态:%@ | 进度:%ld/%ld", run, (long)self.currentCycle, (long)self.totalCycles];
|
||||
self.startButton.enabled = !self.running;
|
||||
self.startButton.alpha = self.running ? 0.5 : 1.0;
|
||||
self.stopButton.enabled = self.running;
|
||||
self.stopButton.alpha = self.running ? 1.0 : 0.5;
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user