Проверьте, поддерживает ли устройство UIFeedbackGenerator в iOS 10
В iOS 10 появился новый API, который позволяет разработчикам использовать движок Taptic, UIFeedbackGenerator.
Хотя этот API доступен в iOS 10, он работает только на новых устройствах iPhone 7 и 7 плюс. Он не работает на старых устройствах, включая 6S или 6S Plus, даже те, которые имеют движок Taptic. Я думаю, что ленточный двигатель на 7 и 7 плюс отличается более мощным.
Я не могу найти способ узнать, поддерживает ли устройство использование нового API. Я хотел бы заменить какой-нибудь вибрирующий код на тачетный код, где это имеет смысл.
Редактировать:
Добавление 3 конкретных подклассов для целей поиска: UIImpactFeedbackGenerator UINotificationFeedbackGenerator UISelectionFeedbackGenerator
Изменить 2:
У меня есть теория, но нет устройства iPhone 7, чтобы проверить его, так что если у вас есть, попробуйте. UIFeedbackGenerator имеет методы, называемые prepare(). При печати экземпляра UIImpactFeedbackGenerator я заметил, что он напечатал свойство с именем "prepare", которое будет показывать 0. Вызов метода prepare () в симуляторе или на iPhone 6S, а затем распечатка экземпляра по-прежнему показывает подготовленный как 0. Может кто-то вызвать метод prepare () для экземпляра UIImpactFeedbackGenerator с iPhone7, а затем распечатайте экземпляр на консоль, чтобы узнать, установлено ли подготовленное значение 1? Это значение не раскрывается, но может быть способ получить эту информацию без использования частного API.
3 ответа
Таким образом, по-видимому, это можно сделать с помощью частного вызова API.
Objective-C:
[[UIDevice currentDevice] valueForKey:@"_feedbackSupportLevel"];
Swift:
UIDevice.currentDevice().valueForKey("_feedbackSupportLevel");
... Эти методы, кажется, возвращают:
0
= Таптика недоступна1
= Первое поколение (протестировано на iPhone 6s) ... которое НЕ поддерживаетUINotificationFeedbackGenerator
, так далее.2
= Второе поколение (протестировано на iPhone 7) ... которое поддерживает его.
К сожалению, здесь есть две оговорки:
- Используя их, Apple может отклонить ваше приложение во время обзора приложений в App Store, но в настоящее время, похоже, другого пути нет.
- Мы не знаем, что представляют собой фактические значения.
Особая благодарность Тиму Оливеру и Стиву TS за помощь в тестировании этого на разных устройствах. https://twitter.com/TimOliverAU/status/778105029643436033
В настоящее время лучшим способом является проверка модели устройства с помощью:
public extension UIDevice
public func platform() -> String {
var sysinfo = utsname()
uname(&sysinfo) // ignore return value
return String(bytes: Data(bytes: &sysinfo.machine, count: Int(_SYS_NAMELEN)), encoding: .ascii)!.trimmingCharacters(in: .controlCharacters)
}
}
Названия платформ для iPhone 7 и 7 плюс: "iPhone9,1", "iPhone9,3", "iPhone9,2", "iPhone9,4"
Источник: iOS: Как определить текущую модель iPhone/ устройства в Swift?
Вы можете создать функцию:
public extension UIDevice {
public var hasHapticFeedback: Bool {
return ["iPhone9,1", "iPhone9,3", "iPhone9,2", "iPhone9,4"].contains(platform())
}
}
class func isFeedbackSupport() -> Bool {
if let value = UIDevice.current.value(forKey: "_feedbackSupportLevel") {
let result = value as! Int
return result == 2 ? true : false
}
return false
}
Я расширил ответ Крисаманс. Он извлекает номер поколения из идентификатора модели и проверяет, равен он или больше 9. Должен работать с будущими моделями iPhone, если Apple не решит ввести новую внутреннюю схему именования.
public extension UIDevice {
var modelIdentifier: String {
var sysinfo = utsname()
uname(&sysinfo) // ignore return value
return String(bytes: Data(bytes: &sysinfo.machine, count: Int(_SYS_NAMELEN)), encoding: .ascii)!.trimmingCharacters(in: .controlCharacters)
}
var hasHapticFeedback: Bool {
// assuming that iPads and iPods don't have a Taptic Engine
if !modelIdentifier.contains("iPhone") {
return false
}
// e.g. will equal to "9,5" for "iPhone9,5"
let subString = String(modelIdentifier[modelIdentifier.index(modelIdentifier.startIndex, offsetBy: 6)..<modelIdentifier.endIndex])
// will return true if the generationNumber is equal to or greater than 9
if let generationNumberString = subString.components(separatedBy: ",").first,
let generationNumber = Int(generationNumberString),
generationNumber >= 9 {
return true
}
return false
}
}
Используйте это так:
if UIDevice.current.hasHapticFeedback {
// work with taptic engine
} else {
// fallback for older devices
}