Files
featherVoice/QXLive/Manager/QXHapticManager.m
2025-12-06 16:55:26 +08:00

173 lines
5.1 KiB
Objective-C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// QXQXQXHapticManager.m
// QXLive
//
// Created by 启星 on 2025/12/5.
//
#import "QXHapticManager.h"
#import <sys/utsname.h>
@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