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

检查设备是否支持iOS 10中的UIFeedbackGenerator,ios,iphone,ios10,taptic-engine,Ios,Iphone,Ios10,Taptic Engine,在iOS 10中,有一个新的api,允许开发人员使用taptic引擎UIFeedbackGenerator 虽然此api在iOS 10中可用,但它仅适用于新设备iPhone 7和7 plus。它不适用于包括6S或6S Plus在内的旧设备,即使是那些有taptic引擎的设备。我想7和7 plus上的taptic引擎是另一个更强大的引擎 我似乎找不到一种方法来查看设备是否支持使用新的api。我想用taptic代码替换一些振动代码,这是有意义的 编辑: 为搜索目的添加3个具体子类: 冲击反馈发生器

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

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

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

编辑:

为搜索目的添加3个具体子类: 冲击反馈发生器 UINotificationFeedbackGenerator UIS选择反馈发生器

编辑2:


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

因此,显然这可以通过专用API调用完成

目标-C:

[[UIDevice currentDevice]valueForKey:@“\u反馈支持级别”]

Swift:

UIDevice.currentDevice().valueForKey(“反馈支持级别”)


。。。这些方法似乎会返回:

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

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

  • 在应用商店的应用程序审查中,使用这些可能会导致你的应用程序被苹果拒绝,但目前似乎没有其他方法
  • 我们不知道实际值代表什么

  • 特别感谢蒂姆·奥利弗和史蒂夫·T-S,感谢他们帮助用不同的设备进行测试

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

    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)
        }
    }
    
    iPhone7和7 plus的平台名称是:
    “iPhone9,1”、“iPhone9,3”、“iPhone9,2”、“iPhone9,4”

    资料来源:

    您可以创建一个函数:

    public extension UIDevice {
        public var hasHapticFeedback: Bool {
            return ["iPhone9,1", "iPhone9,3", "iPhone9,2", "iPhone9,4"].contains(platform())
        } 
    }
    
    我已经延长了。它从模型标识符中提取生成编号,并检查其是否等于或大于9。除非苹果决定引入一个新的内部命名方案,否则应该与未来的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
        }
    
    }
    

    根据我阅读的内容,您不需要检查设备是否支持这些API。在较旧的设备上调用时,对它们的调用将保持沉默。@AndyIbanez我确实需要检查一下,以达到我自己的目的。我在振动和敲击反馈之间切换,我不想在支持它的设备上同时播放这两种反馈。如果不可用,我们会退回到标准的“设备振动”,因为以前的操作系统版本和较旧的硬件上都使用过这种方式。需要知道是否有可能以触觉的方式进行操作。@BenGuild您能否提供一个链接,链接到有关这方面的文档。我确实试过了,但没有得到震动。@KrisGellci如前所述,我还需要知道这是否可行。有人提到,
    UIDevice
    上有一些标志,可能可以检查,但它不是一个公共API。但你的问题是,下一代iPhone何时问世,它们显然不支持它。是的,这是一个问题,如果需要,应该更新代码。但目前,这是一种可能的解决方案,而不是使用私有API。另一个问题是用户可以在设备设置中禁用触觉反馈,此解决方案将不包括这些内容。向公共API公开可用性检查绝对值得关注。@BenGuild为什么使用此方法的应用程序会被苹果拒绝?这在iOS 11上不再适用。将导致崩溃,原因是
    此类不符合key _feedbackSupportLevel的键值编码。
    。您回答的不仅是当前问题,将来还会被其他用户使用。请添加解释。效果很好,但为什么在开始时使用“类”。。。如果在代码中引入此代码,定义的“func”就足够了,不是吗???无法再访问iOS 11中的私钥“\u feedbackupportlevel”。这将导致你的应用程序崩溃。这是一个很好的答案,它不依赖于私有API,为未来减少头痛和汗水,谢谢!
    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
    }