My app uses UIBlurEffect
, however older devices (specifically iPads 2 and 3, that support iOS 8) don't have blur support.
I'd like to check if the user's device has blur support or not. How do I do it?
My app uses UIBlurEffect
, however older devices (specifically iPads 2 and 3, that support iOS 8) don't have blur support.
I'd like to check if the user's device has blur support or not. How do I do it?
UIDevice
has an internal method [UIDevice _graphicsQuality]
that seems promising, but of course your app will be rejected by Apple. Let's create our own method:
First of all, we need to know the exact device type we're working on:
#import <sys/utsname.h>
NSString* deviceName()
{
struct utsname systemInfo;
uname(&systemInfo);
return [NSString stringWithCString:systemInfo.machine
encoding:NSUTF8StringEncoding];
}
This should return iPad2,1
for iPad 2, for example. Here's an updated list of iDevice models: https://theiphonewiki.com/wiki/Models
So, let's classify our device models in two groups: those that have poor graphics quality (and thus don't support blur), and those with great graphics quality. According to my investigation, these are the devices that Apple considers with "poor" graphics (these may change in the future):
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
So we write the following code:
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
}
Be careful because even though the device may support blur, the user may have disabled advanced visual effects from Settings, Accessibility.
Alternative method
Here is a Swift version of Daniel Martin's answer. Some of the code was adapted from 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
}
Many thanks do Daniel Martin for the great answer. I have made a UIDevice category that combines the following checks for availability of the blur effect:
iOS version
Device type (thanks to Daniel Martin)
Private UIDevice method _graphicsQuality when building for the simulator. (This is done since the device type check does not work in the simulator - will be compiled out when building for arm architectures)
'Reduce Transparency' accessibility setting
I've made a gist containing the category: https://gist.github.com/mortenbekditlevsen/5a0ee16b73a084ba404d
And a small writeup about the issue as a whole:
Note: When using the gist, don't forget to subscribe to the
UIAccessibilityReduceTransparencyStatusDidChangeNotificationnotification to refresh the UI when the accessibility setting changes.
I hope that someone finds this useful. :-)
Here are a few ways to do this:
if objc_getClass("UIBlurEffect") != nil {
// UIBlurEffect exists
} else {
// UIBlurEffect doesn't exist
}
Or with access to the blurEffect class
if let blurEffect: AnyClass = NSClassFromString("UIBlurEffect") {
// UIBlurEffect exists
} else {
// UIBlurEffect doesn't exist
}
There's actually a duplicate question here, although the title probably doesn't make it easy to find: How do I do weak linking in Swift?
-- Edit --
Misunderstood the question. There appears to be no way to find this out short of checking the device name:
Detect if device properly displays UIVisualEffectView?
I would rely on whatever Apple's fallback implementation is. It looks like they still apply the tint color so that is probably fine in most cases. If you really must change the appearance when no blur will be applied, I think device name is not terrible since they specifically outlined which devices do not support blur.
© 2022 - 2024 — McMap. All rights reserved.
systemInfo.machine
property is x86_64 (on my Mac); – Stoichiometric