173 lines
5.1 KiB
Mathematica
173 lines
5.1 KiB
Mathematica
|
|
//
|
|||
|
|
// 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
|