检查设备是否支持iOS 10中的UIFeedbackGenerator

时间:2016-09-19 02:21:50

标签: ios iphone ios10 taptic-engine

在iOS 10中,有一个新的API允许开发人员使用tapic引擎UIFeedbackGenerator。

虽然这款api在iOS 10中可用,但它仅适用于新设备,iPhone 7和7 plus。它不适用于包括6S或6S Plus在内的旧设备,即使是那些具有tapic引擎的设备也是如此。我猜7和7 plus上的taptic引擎是一个不同的更强大的引擎。

我似乎无法找到一种方法来查看设备是否支持使用新的api。我想用taptic代码替换一些振动代码,这是有意义的。

编辑:

为搜索目的添加3个具体子类: UIImpactFeedbackGenerator UINotificationFeedbackGenerator UISelectionFeedbackGenerator

编辑2:

我有一个理论,但没有iPhone 7设备来测试它,所以如果你有一个,请试一试。 UIFeedbackGenerator有一个名为prepare()的方法。当打印出UIImpactFeedbackGenerator的一个实例时,我注意到它打印了一个名为“prepared”的属性,它将显示0.在模拟器或iPhone 6S上调用prepare()然后打印出实例仍然显示准备为0.可以有人打电话准备()来自iPhone7的UIImpactFeedbackGenerator实例,然后将实例打印到控制台以查看是否将prepare设置为1?此值未公开,但可能有一种方法可以使用私有apis获取此信息。

4 个答案:

答案 0 :(得分:13)

所以,显然这可以通过私有API调用完成。

<强>目标-C:

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

<强>夫特:

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

......这些方法似乎回归:

  • 0 = Taptic not available
  • 1 =第一代(在iPhone 6s上测试过)...不支持UINotificationFeedbackGenerator等。
  • 2 =第二代(在iPhone 7上测试)...... 支持支持它。

不幸的是,这里有两点需要注意:

  1. 在App Store的App Review期间使用这些可能会让Apple拒绝您的应用,但目前似乎没有其他任何方式。
  2. 我们不知道实际值代表什么。
  3. 特别感谢 Tim Oliver Steve T-S 帮助使用不同的设备进行测试。 https://twitter.com/TimOliverAU/status/778105029643436033

答案 1 :(得分:1)

目前,最好的方法是使用以下方法检查设备的型号:

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 plus的平台名称为:"iPhone9,1", "iPhone9,3", "iPhone9,2", "iPhone9,4"

来源:iOS: How to determine the current iPhone/device model in Swift?

您可以创建一个功能:

public extension UIDevice {
    public var hasHapticFeedback: Bool {
        return ["iPhone9,1", "iPhone9,3", "iPhone9,2", "iPhone9,4"].contains(platform())
    } 
}

答案 2 :(得分:0)

class func isFeedbackSupport() -> Bool {
    if let value = UIDevice.current.value(forKey: "_feedbackSupportLevel") {
        let result = value as! Int
        return result == 2 ? true : false
    }
    return false
}

答案 3 :(得分:0)

我已经扩展了chrisamanse's answer。它从型号标识符中提取世代号,并检查它是否等于或大于9。除非苹果决定采用新的内部命名方案,否则它应与将来的iPhone型号一起使用。

=LOOKUP(C2, {-1E+99,1,11,21,31,41}, {"!","R","B","Y","G","!"})

像这样使用它:

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
    }

}