【问题标题】:Check if device supports blur检查设备是否支持模糊
【发布时间】:2015-01-10 17:02:17
【问题描述】:

我的应用使用UIBlurEffect,但较旧的设备(特别是支持 iOS 8 的 iPad 2 和 3)不支持模糊。

我想检查用户的设备是否支持模糊。我该怎么做?

【问题讨论】:

    标签: ios swift uiblureffect


    【解决方案1】:

    UIDevice 有一个内部方法[UIDevice _graphicsQuality] 看起来很有希望,但你的应用当然会被 Apple 拒绝。让我们创建自己的方法:

    首先,我们需要知道我们正在处理的确切设备类型:

    #import <sys/utsname.h>
    
    NSString* deviceName()
    {
        struct utsname systemInfo;
        uname(&systemInfo);
    
        return [NSString stringWithCString:systemInfo.machine
                                  encoding:NSUTF8StringEncoding];
    }
    

    例如,对于 iPad 2,这应该返回 iPad2,1。以下是更新的 iDevice 型号列表:https://theiphonewiki.com/wiki/Models

    因此,让我们将我们的设备型号分为两组:图形质量较差(因此不支持模糊)的机型和图形质量出色的机型。根据我的调查,这些是 Apple 认为图形“差”的设备(将来可能会改变):

    iPad iPad1,1 iPhone1,1 iPhone1,2 iPhone2,1 iPhone3,1 iPhone3,2 iPhone3,3 iPod1,1 iPod2,1 iPod2,2 iPod3,1 iPod4,1 iPad2,1 iPad2,2 iPad2,3 iPad2,4 iPad3,1 iPad3,2 iPad3,3

    所以我们编写如下代码:

    NSSet *graphicsQuality = [NSSet setWithObjects:@"iPad",
                                                         @"iPad1,1",
                                                         @"iPhone1,1",
                                                         @"iPhone1,2",
                                                         @"iPhone2,1",
                                                         @"iPhone3,1",
                                                         @"iPhone3,2",
                                                         @"iPhone3,3",
                                                         @"iPod1,1",
                                                         @"iPod2,1",
                                                         @"iPod2,2",
                                                         @"iPod3,1",
                                                         @"iPod4,1",
                                                         @"iPad2,1",
                                                         @"iPad2,2",
                                                         @"iPad2,3",
                                                         @"iPad2,4",
                                                         @"iPad3,1",
                                                         @"iPad3,2",
                                                         @"iPad3,3",
                                                         nil];
     if ([graphicsQuality containsObject:deviceName()]) {
         // Device with poor graphics, blur not supported
     } else {
         // Blur supported
     }
    

    请小心,因为即使设备可能支持模糊,用户也可能已从“设置”、“辅助功能”中禁用了高级视觉效果。

    替代方法

    https://gist.github.com/conradev/8655650

    【讨论】:

    • 使用模拟器时,systemInfo.machine 属性为 x86_64(在我的 Mac 上);
    【解决方案2】:

    这是 Daniel Martin 答案的 Swift 版本。部分代码改编自here

    func isBlurSupported() -> Bool {
        var supported = Set<String>()
        supported.insert("iPad")
        supported.insert("iPad1,1")
        supported.insert("iPhone1,1")
        supported.insert("iPhone1,2")
        supported.insert("iPhone2,1")
        supported.insert("iPhone3,1")
        supported.insert("iPhone3,2")
        supported.insert("iPhone3,3")
        supported.insert("iPod1,1")
        supported.insert("iPod2,1")
        supported.insert("iPod2,2")
        supported.insert("iPod3,1")
        supported.insert("iPod4,1")
        supported.insert("iPad2,1")
        supported.insert("iPad2,2")
        supported.insert("iPad2,3")
        supported.insert("iPad2,4")
        supported.insert("iPad3,1")
        supported.insert("iPad3,2")
        supported.insert("iPad3,3")
    
        return !supported.contains(hardwareString())
    }
    
    func hardwareString() -> String {
        var name: [Int32] = [CTL_HW, HW_MACHINE]
        var size: Int = 2
        sysctl(&name, 2, nil, &size, &name, 0)
        var hw_machine = [CChar](count: Int(size), repeatedValue: 0)
        sysctl(&name, 2, &hw_machine, &size, &name, 0)
    
        let hardware: String = String.fromCString(hw_machine)!
        return hardware
    }
    

    【讨论】:

      【解决方案3】:

      非常感谢 Daniel Martin 的出色回答。 我制作了一个 UIDevice 类别,它结合了以下模糊效果可用性检查:

      1. iOS 版本

      2. 设备类型(感谢 Daniel Martin)

      3. 为模拟器构建时的私有 UIDevice 方法 _graphicsQuality。 (这样做是因为设备类型检查在模拟器中不起作用 - 将在为 arm 架构构建时编译出来)

      4. “降低透明度”可访问性设置

      我做了一个包含类别的要点: https://gist.github.com/mortenbekditlevsen/5a0ee16b73a084ba404d

      还有一个关于整个问题的小文章:

      http://mojoapps.dk/?p=1

      注意:使用gist时,别忘了订阅

       UIAccessibilityReduceTransparencyStatusDidChangeNotification
      通知可在可访问性设置更改时刷新 UI。

      我希望有人觉得这很有用。 :-)

      【讨论】:

        【解决方案4】:

        这里有几种方法可以做到这一点:

        if objc_getClass("UIBlurEffect") != nil {
           // UIBlurEffect exists
        } else {
           // UIBlurEffect doesn't exist
        }
        

        或者可以访问 blurEffect 类

        if let blurEffect: AnyClass = NSClassFromString("UIBlurEffect") {
            // UIBlurEffect exists
        } else {
            // UIBlurEffect doesn't exist
        }
        

        这里实际上有一个重复的问题,虽然标题可能不容易找到:How do I do weak linking in Swift?

        -- 编辑--

        误解了这个问题。除了检查设备名称之外,似乎没有办法找到它:

        Detect if device properly displays UIVisualEffectView?

        我会依赖 Apple 的后备实现。看起来他们仍然应用淡色,所以在大多数情况下可能没问题。如果您真的必须在不应用模糊的情况下更改外观,我认为设备名称并不可怕,因为它们专门列出了哪些设备不支持模糊。

        【讨论】:

        • 这不起作用,因为由于设备运行的是 iOS 8,因此该类确实存在,但在旧设备上,模糊视图的渲染方式与新设备不同。
        • 抱歉,没有注意到问题的最后一部分。我相信如果不检查设备名称,就无法检查这一点。
        猜你喜欢
        • 2013-10-25
        • 1970-01-01
        • 2018-09-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-01-26
        • 1970-01-01
        • 2014-08-09
        相关资源
        最近更新 更多