web-dev-qa-db-fra.com

Vérifier si le périphérique prend en charge UIFeedbackGenerator dans iOS 10

Dans iOS 10, une nouvelle API permet aux développeurs d'utiliser le moteur de taptic UIFeedbackGenerator.

Bien que cette API soit disponible sous iOS 10, elle ne fonctionne que sur les nouveaux appareils, iPhone 7 et 7 plus. Il ne fonctionne pas sur les appareils plus anciens, y compris les 6S et 6S Plus, même ceux qui ont un moteur à bande. Je suppose que le moteur à bande sur les 7 et 7 plus est un moteur plus puissant et différent.

Je n'arrive pas à trouver un moyen de voir si l'appareil prend en charge l'utilisation de la nouvelle API. Je voudrais remplacer certains codes vibrants par des codes tapiques, là où cela a du sens. 

Modifier:

Ajouter les 3 sous-classes concrètes aux fins de recherche: UIImpactFeedbackGenerator UINotificationFeedbackGenerator UISélectionnerFeedbackGenerator

Edit 2:

J'ai une théorie mais pas d'appareil iPhone 7 pour le tester, donc si vous en avez un, tentez votre chance. UIFeedbackGenerator a une méthode appelée prepare (). Lors de l’impression d’une instance de UIImpactFeedbackGenerator, j’ai remarqué qu’elle imprimait une propriété nommée "préparé" qui afficherait 0. L’appel prepare () dans le simulateur ou sur l’iPhone 6S, puis l’impression afficherait toujours préparé comme étant 0. Quelqu'un peut-il appeler () sur une instance de UIImpactFeedbackGenerator à partir d'un iPhone7, puis imprimez l'instance sur la console pour voir si préparé est défini sur 1? Cette valeur n’est pas exposée, mais il peut exister un moyen d’obtenir cette information sans passer par un apis privé.

11
Kris Gellci

Donc, apparemment, cela peut être fait avec un appel d’API privé.

Objectif c:

[[UIDevice currentDevice] valueForKey:@"_feedbackSupportLevel"];

Rapide:

UIDevice.currentDevice().valueForKey("_feedbackSupportLevel");


... Ces méthodes semblent revenir:

  • 0 = Taptic non disponible
  • 1 = Première génération (testé sur un iPhone 6s) ... qui ne supporte pas UINotificationFeedbackGenerator, etc.
  • 2 = Deuxième génération (testé sur un iPhone 7) ... que prend en charge.

Malheureusement, il y a deux mises en garde ici:

  1. Leur utilisation pourrait entraîner le rejet de votre application par Apple lors de l'examen de l'application sur l'App Store, mais il ne semble pas exister d'autre moyen pour le moment.
  2. Nous ne savons pas ce que les valeurs réelles représentent.

Un merci spécial à Tim Oliver et Steve T-S pour avoir aidé à tester cela avec différents appareils. https://Twitter.com/TimOliverAU/status/778105029643436033

13
Ben Guild

Actuellement, le meilleur moyen consiste à vérifier le modèle du périphérique en utilisant:

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)
    }
}

Les noms de plate-forme pour iPhone 7 et 7 plus sont: "iPhone9,1", "iPhone9,3", "iPhone9,2", "iPhone9,4"

Source: iOS: Comment déterminer le modèle actuel d’iPhone/appareil dans Swift?

Vous pouvez créer une fonction:

public extension UIDevice {
    public var hasHapticFeedback: Bool {
        return ["iPhone9,1", "iPhone9,3", "iPhone9,2", "iPhone9,4"].contains(platform())
    } 
}
2
chrisamanse
class func isFeedbackSupport() -> Bool {
    if let value = UIDevice.current.value(forKey: "_feedbackSupportLevel") {
        let result = value as! Int
        return result == 2 ? true : false
    }
    return false
}
1
Wan Mook Kang

J'ai étendu la réponse de chrisamanse . Il extrait le numéro de génération de l'identifiant du modèle et vérifie s'il est égal ou supérieur à 9. Devrait fonctionner avec les futurs modèles d'iPhone, sauf si Apple décide d'introduire un nouveau schéma de dénomination interne.

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
    }

}

Utilisez-le comme suit:

if UIDevice.current.hasHapticFeedback {
    // work with taptic engine
} else {
    // fallback for older devices
}
0
MJQZ1347