// // QXQXQXHapticManager.m // QXLive // // Created by 启星 on 2025/12/5. // #import "QXHapticManager.h" #import @interface QXHapticManager () @property (nonatomic, strong) UIImpactFeedbackGenerator *impactGenerator; @property (nonatomic, strong) UINotificationFeedbackGenerator *notificationGenerator; @property (nonatomic, strong) UISelectionFeedbackGenerator *selectionGenerator; @property (nonatomic, assign) BOOL isImpactPrepared; @property (nonatomic, assign) UIImpactFeedbackStyle preparedStyle; @end @implementation QXHapticManager + (instancetype)shared { static QXHapticManager *instance = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ instance = [[QXHapticManager alloc] init]; }); return instance; } - (instancetype)init { self = [super init]; if (self) { _isImpactPrepared = NO; // 提前初始化所有生成器 _impactGenerator = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleMedium]; _notificationGenerator = [[UINotificationFeedbackGenerator alloc] init]; _selectionGenerator = [[UISelectionFeedbackGenerator alloc] init]; // 提前准备所有生成器 [self prepareAllGenerators]; } return self; } #pragma mark - 支持性检查 + (BOOL)isHapticFeedbackSupported { if (@available(iOS 10.0, *)) { // 检查设备型号是否支持 NSString *deviceModel = [[UIDevice currentDevice] model]; // 检查是否是iPhone 7及以后 // 这里简化检查,实际应使用更精确的设备型号检测 // 可以使用 sysctlbyname 获取更精确的设备信息 struct utsname systemInfo; uname(&systemInfo); NSString *deviceIdentifier = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding]; // iPhone 7及以后的设备标识符(部分示例) NSArray *supportedDevices = @[ @"iPhone9,", @"iPhone10,", @"iPhone11,", @"iPhone12,", @"iPhone13,", @"iPhone14,", @"iPhone15,", @"iPhone16,", @"iPhone8,4" // iPhone SE (第二代) ]; BOOL isSupportedDevice = NO; for (NSString *prefix in supportedDevices) { if ([deviceIdentifier hasPrefix:prefix]) { isSupportedDevice = YES; break; } } // 如果是模拟器,返回YES以支持调试 #if TARGET_IPHONE_SIMULATOR return YES; #else return isSupportedDevice; #endif } return NO; } - (void)prepareAllGenerators { if (![QXHapticManager isHapticFeedbackSupported]) { return; } // 在主线程准备所有生成器 dispatch_async(dispatch_get_main_queue(), ^{ [self.impactGenerator prepare]; [self.notificationGenerator prepare]; [self.selectionGenerator prepare]; }); } #pragma mark - 即时触觉反馈 - (void)impactWithStyle:(UIImpactFeedbackStyle)style { if (![QXHapticManager isHapticFeedbackSupported]) { return; } dispatch_async(dispatch_get_main_queue(), ^{ // 创建新的生成器确保每次都触发 UIImpactFeedbackGenerator *generator = [[UIImpactFeedbackGenerator alloc] initWithStyle:style]; [generator prepare]; [generator impactOccurred]; // 延迟释放 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [generator prepare]; }); }); } - (void)impactMedium { [self impactWithStyle:UIImpactFeedbackStyleMedium]; } #pragma mark - 带准备的触觉反馈 - (void)prepareImpactWithStyle:(UIImpactFeedbackStyle)style { if (![QXHapticManager isHapticFeedbackSupported]) { return; } self.preparedStyle = style; dispatch_async(dispatch_get_main_queue(), ^{ // 重新创建生成器 self.impactGenerator = [[UIImpactFeedbackGenerator alloc] initWithStyle:style]; [self.impactGenerator prepare]; self.isImpactPrepared = YES; }); } - (void)triggerPreparedImpact { if (![QXHapticManager isHapticFeedbackSupported] || !self.isImpactPrepared) { return; } dispatch_async(dispatch_get_main_queue(), ^{ if (self.impactGenerator) { [self.impactGenerator impactOccurred]; // 准备下一次 [self.impactGenerator prepare]; } }); } #pragma mark - 其他类型的触觉反馈 - (void)notificationWithType:(UINotificationFeedbackType)type { if (![QXHapticManager isHapticFeedbackSupported]) { return; } dispatch_async(dispatch_get_main_queue(), ^{ [self.notificationGenerator notificationOccurred:type]; [self.notificationGenerator prepare]; }); } - (void)selectionChanged { if (![QXHapticManager isHapticFeedbackSupported]) { return; } dispatch_async(dispatch_get_main_queue(), ^{ [self.selectionGenerator selectionChanged]; [self.selectionGenerator prepare]; }); } @end