Проверьте, поддерживает ли устройство 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) ... которое поддерживает его.

К сожалению, здесь есть две оговорки:

  1. Используя их, Apple может отклонить ваше приложение во время обзора приложений в App Store, но в настоящее время, похоже, другого пути нет.
  2. Мы не знаем, что представляют собой фактические значения.

Особая благодарность Тиму Оливеру и Стиву 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
}
Другие вопросы по тегам