I need to detect latest iphone devices programatically. I have all the device identifiers for previous models but i need the device identifiers for iPhone Xs max ,iPhone Xs, iPhone X(R).
For XCode 9 and Swift 4
extension UIDevice {
var iPhoneX: Bool {
return UIScreen.main.nativeBounds.height == 2436
}
var iPhone: Bool {
return UIDevice.current.userInterfaceIdiom == .phone
}
enum ScreenType: String {
case iPhones_4_4S = "iPhone 4 or iPhone 4S"
case iPhones_5_5s_5c_SE = "iPhone 5, iPhone 5s, iPhone 5c or iPhone SE"
case iPhones_6_6s_7_8 = "iPhone 6, iPhone 6S, iPhone 7 or iPhone 8"
case iPhones_6Plus_6sPlus_7Plus_8Plus = "iPhone 6 Plus, iPhone 6S Plus, iPhone 7 Plus or iPhone 8 Plus"
case iPhones_X_XS = "iPhone X or iPhone XS"
case iPhone_XR = "iPhone XR"
case iPhone_XSMax = "iPhone XS Max"
case unknown
}
var screenType: ScreenType {
switch UIScreen.main.nativeBounds.height {
case 960:
return .iPhones_4_4S
case 1136:
return .iPhones_5_5s_5c_SE
case 1334:
return .iPhones_6_6s_7_8
case 1792:
return .iPhone_XR
case 1920, 2208:
return .iPhones_6Plus_6sPlus_7Plus_8Plus
case 2436:
return .iPhones_X_XS
case 2688:
return .iPhone_XSMax
default:
return .unknown
}
}
}
And use this simply:
print("screen Type:", UIDevice.current.screenType.rawValue)
Also can visit this for knowing about iPhone devices screen resolution.
https://www.paintcodeapp.com/news/ultimate-guide-to-iphone-resolutions
Related
In my application, I was implemented pull-to-refresh feature and custom loading icon. In IPhone which has dynamic island, It was overlapsed my loading icon.
I want to detect device which has dynamic island or not. If it has, I will add some top space to it.
Currently, as far as I know, dynamic island is will included in ActivityKit on late of 2022. You can check from this link for ActivityKit and Apple's thread about it. And Apple doesn't provide way to check dynamic island is on device or not.
But there is a workaround for you to get the thing you want. Currently dynamic island only available on iPhone 14 Pro and iPhone 14 Pro Max. So just need to check this both device.
Update: Thanks to this link for type model, name model type of iPhone 14 Pro and iPhone 14 Pro Max is iPhone15,2 and iPhone15,3 so we just need to check these case.
Code will be like this
extension UIDevice {
func checkIfHasDynamicIsland() -> Bool {
if let simulatorModelIdentifier = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] {
let nameSimulator = simulatorModelIdentifier
return nameSimulator == "iPhone15,2" || nameSimulator == "iPhone15,3" ? true : false
}
var sysinfo = utsname()
uname(&sysinfo) // ignore return value
let name = String(bytes: Data(bytes: &sysinfo.machine, count: Int(_SYS_NAMELEN)), encoding: .ascii)!.trimmingCharacters(in: .controlCharacters)
return name == "iPhone15,2" || name == "iPhone15,3" ? true : false
}
}
Usage
let value = UIDevice().checkIfHasDynamicIsland()
print("value: ", value)
According to the live activity documentation, we can only detect whether the device supports Live activity, but we don't know if the device has dynamic island
I use the window safeAreaInsets value to detect dynamic island. when the device orientation is portrait, safeAreaInsets.top is equal to 59(Display Zoom Default),
or 51(Display Zoom Large Text).
This is likely to support the iPhone15 Pro/iPhone15 Pro Max and later models.
usage: print(UIDevice.current.hasDynamicIsland)
extension UIDevice {
// Get this value after sceneDidBecomeActive
var hasDynamicIsland: Bool {
// 1. dynamicIsland only support iPhone
guard userInterfaceIdiom == .phone else {
return false
}
// 2. Get key window, working after sceneDidBecomeActive
guard let window = (UIApplication.shared.connectedScenes.compactMap { $0 as? UIWindowScene }.flatMap { $0.windows }.first { $0.isKeyWindow}) else {
print("Do not found key window")
return false
}
// 3.It works properly when the device orientation is portrait
return window.safeAreaInsets.top >= 51
}
}
This is what I mean.
enum Device {
case iPhone_13Pro, iPhone_12Pro
case iPadPro_129
case iPadPro_11
}
// Hypothetical Scenario
enum Device_Group {
case iPhones
case iPads
}
Is there any way to do as above to represent a certain group of cases like this (it can be another enum OR a different case within the same enum - so that I could do as below?
// DO THIS
switch device {
case iPhones:
print("These are iPhones")
case iPads:
print("These are iPads")
}
// INSTEAD OF THIS
switch device {
case .iPhone_13Pro, .iPhone_12Pro:
print("These are iPhones")
case .iPadPro_129, .iPadPro_11:
print("These are iPads")
}
I dont know if this might be a weird question, but I find that grouping multiple cases has a certain benefit while using a switch statement. Would appreciate any advise on this. Thanks in advance.
You can used nested Enum and a case with parameter
enum Devices {
case phone(iPhone)
case tablet(iPad)
enum iPhone {
case phone7
case phoneX
}
enum iPad {
case mini
case pro
}
}
let randomDevice = Devices.phone(.phone7)
switch randomDevice {
case .phone:
print("Its a phone")
default:
break
}
// prints "Its a phone"
You can define two different enums for iPhones and iPads and then use them as Associated Values for Devices's types.
https://docs.swift.org/swift-book/LanguageGuide/Enumerations.html
enum Ipad {
case iPadAir
case iPadPro
}
enum Iphone {
case iPhone12
case iPhone13
}
enum Device {
case iPad(model: Ipad)
case iPhone(model: Iphone)
}
func findDeviceType(device: Device) {
switch device {
case .iPad:
print("iPad")
case .iPhone:
print("iPhone")
}
}
findDeviceType(device: Device.iPad(model: .iPadAir)) // iPad
You can look at OptionSet as well and it's flexible approach to group and serialize your items because they have unique values. For instance:
struct Device: OptionSet {
let rawValue: Int
static let iPhone_13Pro = Self(rawValue: 1 << 0)
static let iPhone_12Pro = Self(rawValue: 1 << 1)
static let iPadPro_129 = Self(rawValue: 1 << 2)
static let iPadPro_11 = Self(rawValue: 1 << 3)
static let iPhone: Self = [.iPhone_13Pro, .iPhone_12Pro]
static let iPad: Self = [.iPadPro_129, .iPadPro_11]
static let all: Self = [.iPhone, .iPad]
}
let device = Device.iPhone_13Pro
if Device.iPhone.contains(device) {
print("It's iPhone")
}
This question already has answers here:
How to choose a random enumeration value
(9 answers)
Closed 4 years ago.
enum TrackingEvent: String {
case notificationScreenLoaded = "Notification Screen"
case homeScreenLoaded = "Home Screen"
case homeScreenViewBill = "Home Screen View Bill Button"
case homeScreenPayBill = "Home Screen Pay Bill Button"
case homeScreenViewLastPayment = "Home Screen Last Payment Section"
case chartToggleUsage = "Charts Toggle"
case chartExplanation = "Charts Explanation Screen"
}
for this example, how do I get a random string? So far what I search in StackOverflow examples the enum are all UInt32 return type
Put all into an array and emit a random index item,
extension TrackingEvent {
static func random() -> TrackingEvent {
let all: [TrackingEvent] = [.notificationScreenLoaded,
.homeScreenLoaded,
.homeScreenViewBill,
.homeScreenPayBill,
.homeScreenViewLastPayment,
.chartToggleUsage,
.chartExplanation]
let randomIndex = Int(arc4random()) % all.count
return all[randomIndex]
}
}
You need to create a function to get random UInt32 with upper bound equal to the number of cases in the enum TrackingEvent and return the case based on a random number.
enum TrackingEvent: String {
case notificationScreenLoaded = "Notification Screen"
case homeScreenLoaded = "Home Screen"
case homeScreenViewBill = "Home Screen View Bill Button"
case homeScreenPayBill = "Home Screen Pay Bill Button"
case homeScreenViewLastPayment = "Home Screen Last Payment Section"
case chartToggleUsage = "Charts Toggle"
case chartExplanation = "Charts Explanation Screen"
static func random() -> TrackingEvent {
let rand = arc4random_uniform(7)
switch rand {
case 1:
return .homeScreenLoaded
case 2:
return .homeScreenViewBill
case 3:
return .homeScreenPayBill
case 4:
return .homeScreenViewLastPayment
case 5:
return .chartToggleUsage
case 6:
return .chartExplanation
default:
return .notificationScreenLoaded
}
}
}
You can use it like
let random = TrackingEvent.random()
I want to be able to only allow a api to be called if the version is 10.*. I know usually we use #available(10.0, *), but this means 10 and above.
How do i restrict 10 to <11?
Here is the persudo code:
if device is ios10 but less than 11 {
//Do this only for iOS10.*
}
You can use #available instead of #available, just tested this and it seems to do what you need:
if #available(iOS 11.0, *) {
// leave blank if you don't need to do anything here
} else if #available(iOS 10.0, *) {
print("You're on iOS 10!")
}
You can use code:
let os = ProcessInfo().operatingSystemVersion
switch (os.majorVersion, os.minorVersion) {
case (10, 0): // iOS 10.0
// Do your code
default:
break // Some other version
}
Or if you want to use for all 10.* versions of OS, then simply skip minor version:
let os = ProcessInfo().operatingSystemVersion
if os.majorVersion == 10 {
// Do your code
}
I registered UIMutableUserNotificationAction:
let responseTextAction = UIMutableUserNotificationAction()
responseTextAction.identifier = "text"
responseTextAction.title = "New text"
if #available(iOS 9.0, *) {
responseTextAction.behavior = UIUserNotificationActionBehavior.TextInput
} else {
// Fallback on earlier versions
}
This is screenshot from iOS 9:
and from iOS 8:
How can I implement text input for iOS 8 also.
Text Input for Notifications is only available in iOS 9+. Previous versions will default to a standard notification as you have seen.