16

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

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

我似乎找不到查看设备是否支持使用新 api 的方法。我想在有意义的地方用敲击代码替换一些振动代码。

编辑:

添加 3 个具体的子类用于搜索: UIImpactFeedbackGenerator UINotificationFeedbackGenerator UISelectionFeedbackGenerator

编辑2:

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

4

4 回答 4

15

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

目标-C:

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

迅速:

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


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

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

不幸的是,这里有两个警告:

  1. 使用这些可能会让您的应用在 App Store 的 App Review 期间被 Apple 拒绝,但目前似乎没有任何其他方式。
  2. 我们不知道实际值代表什么。

特别感谢Tim OliverSteve TS帮助测试不同的设备。https://twitter.com/TimOliverAU/status/778105029643436033

于 2016-09-20T10:58:58.070 回答
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:如何在 Swift 中确定当前的 iPhone/设备型号?

您可以创建一个函数:

public extension UIDevice {
    public var hasHapticFeedback: Bool {
        return ["iPhone9,1", "iPhone9,3", "iPhone9,2", "iPhone9,4"].contains(platform())
    } 
}
于 2016-12-23T09:04:44.007 回答
1

我已经扩展了 chrisamanse 的答案。它从型号标识符中提取代号并检查它是否等于或大于 9。除非 Apple 决定引入新的内部命名方案,否则它应该适用于未来的 iPhone 型号。

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
}
于 2018-12-29T11:11:56.853 回答
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
}
于 2017-03-10T07:12:15.537 回答