Swift - Action based on different size devices [duplicate] - swift

This question already has answers here:
How to determine the current iPhone/device model?
(32 answers)
Closed 3 years ago.
What I'm trying to achieve is to set different actions based on their device type.
So for example: If I want to do different stuff for an iPhone 8
if device type is = iPhone 8
{
//action here
...
}
And so on for each device

Use this
struct DeviceType {
static let IS_IPHONE_4_OR_LESS = UIDevice.current.userInterfaceIdiom ==
.phone
&& ScreenSize.SCREEN_MAX_LENGTH < 568.0
static let IS_IPHONE_5 = UIDevice.current.userInterfaceIdiom == .phone &&
ScreenSize.SCREEN_MAX_LENGTH == 568.0
static let IS_IPHONE_6 = UIDevice.current.userInterfaceIdiom == .phone &&
ScreenSize.SCREEN_MAX_LENGTH == 667.0
static let IS_IPHONE_6S = UIDevice.current.userInterfaceIdiom == .phone &&
ScreenSize.SCREEN_MAX_LENGTH == 667.0
static let IS_IPHONE_7 = UIDevice.current.userInterfaceIdiom == .phone &&
ScreenSize.SCREEN_MAX_LENGTH == 667.0
static let IS_IPHONE_8 = UIDevice.current.userInterfaceIdiom == .phone &&
ScreenSize.SCREEN_MAX_LENGTH == 667.0
static let IS_IPHONE_6P = UIDevice.current.userInterfaceIdiom == .phone &&
ScreenSize.SCREEN_MAX_LENGTH == 736.0
static let IS_IPHONE_X = UIDevice.current.userInterfaceIdiom == .phone &&
ScreenSize.SCREEN_MAX_LENGTH == 812.0
static let IS_IPHONE_XR = UIDevice.current.userInterfaceIdiom == .phone &&
ScreenSize.SCREEN_MAX_LENGTH == 896.0
static let IS_IPAD = UIDevice.current.userInterfaceIdiom == .pad &&
ScreenSize.SCREEN_MAX_LENGTH == 1024.0
static let IS_IPAD_PRO = UIDevice.current.userInterfaceIdiom == .pad &&
ScreenSize.SCREEN_MAX_LENGTH == 1366.0
}

I think you shoud use this library:
https://github.com/lmirosevic/GBDeviceInfo
With this library you can write the code you asked for and you get tons of other features (obtaining device information) for free
if (deviceInfo.model == GBDeviceModeliPhone6) {
print("It's an iPhone 6")
}

well you can do different stuff by using this below code by using it in your class so, you can set set action accordingly :=
struct Device {
// iDevice detection code
static let IS_IPAD = UIDevice.current.userInterfaceIdiom == .pad
static let IS_IPHONE = UIDevice.current.userInterfaceIdiom == .phone
static let IS_RETINA = UIScreen.main.scale >= 2.0
static let SCREEN_WIDTH = Int(UIScreen.main.bounds.size.width)
static let SCREEN_HEIGHT = Int(UIScreen.main.bounds.size.height)
static let SCREEN_MAX_LENGTH = Int( max(SCREEN_WIDTH, SCREEN_HEIGHT) )
static let SCREEN_MIN_LENGTH = Int( min(SCREEN_WIDTH, SCREEN_HEIGHT) )
static let IS_IPHONE_4_OR_LESS = IS_IPHONE && SCREEN_MAX_LENGTH < 568
static let IS_IPHONE_5 = IS_IPHONE && SCREEN_MAX_LENGTH == 568
static let IS_IPHONE_6 = IS_IPHONE && SCREEN_MAX_LENGTH == 667
static let IS_IPHONE_7 = IS_IPHONE && SCREEN_MAX_LENGTH == 667
static let IS_IPHONE_8 = IS_IPHONE && SCREEN_MAX_LENGTH == 667
static let IS_IPHONE_6P = IS_IPHONE && SCREEN_MAX_LENGTH == 736
static let IS_IPHONE_X = IS_IPHONE && SCREEN_MAX_LENGTH == 812
}
now you can set constrain like this:==
if(Device.IS_IPHONE_5 || Device.IS_IPHONE_4_OR_LESS){
//--- set your constrain for iphone 5 and 4
}else if(Device.IS_IPAD){
//--- set your constrain for ipad
}else{
//--- set default constrain
}

if UIDevice.current.deviceCategory() == .iPhoneX || UIDevice.current.deviceCategory() == .iPhoneXR {
// Just this checking wherever you want
}
Add extension below then use it.
extension UIDevice {
enum DeviceCategory {
case iPhone4
case iPhone5
case iPhone6
case iPhone6Plus
case iPhoneX
case iPhoneXR
case iPadPro12inch
case iPad
}
func deviceCategory() -> DeviceCategory {
let height = UIScreen.main.bounds.size.height
switch height {
case 480:
return .iPhone4
case 568:
return .iPhone5
case 667:
return .iPhone6
case 736:
return .iPhone6Plus
case 812:
return .iPhoneX
case 896:
return .iPhoneXR
case 1366:
return .iPadPro12inch
default:
return .iPad
}
}
}

Related

how to wait Recursion until the function finish executing

I have one Recursion func that executes the actions and on it's last cycle it checks for a condition, and if the condition is true it calls another similar function that Also runs actions. But while second func is executing actions through recursion the first func starts executing. So have two actions now running simultaneously. I Read about GCD and tried it but didn't get results as expected.(Actually I still don't understand how to use it properly)
First main Func movePiece()
Here's my code it's all in the same class :
func movePiece() {
// some Func Calls here.
if ( self.movesRemaining > 0) {
DispatchQueue.global(qos: .userInteractive).async {
self.moveFinished = false
let currentSpace:Int = self.returnPlayerSpace(player: self.whosTurn)
let spaceNumber:Int = currentSpace
var nextSpace:Int = spaceNumber + 1
let moveAction:SKAction = SKAction.move(to: (self.childNode(withName: String(nextSpace))?.position)!, duration: 0.4)
moveAction.timingMode = .easeOut
let wait:SKAction = SKAction.wait(forDuration: 0.2)
let runAction:SKAction = SKAction.run({
if (self.movesRemaining == 1) {
self.KillHim(player:self.whosTurn, nextspace:nextSpace)
DispatchQueue.main.async {
self.moveBackPiece()
}
}
self.setThePlayerSpace(space: nextSpace, player:self.whosTurn)
if (self.movesRemaining == 1) {
self.Adjust(node: self.childNode(withName: String(nextSpace))!)
}
self.movesRemaining = self.movesRemaining - 1
self.movePiece()
})
if self.whosTurn == .Player1 {
self.touchedNode.run(SKAction.sequence([moveAction, wait, runAction]))
} else {
self.playerPiece.run(SKAction.sequence( [moveAction, wait, runAction]))
}
}
}
}
Here is second func moveBackPiece() :
func moveBackPiece() {
if ((killedPiece == self.Player1Piece1 || killedPiece == self.Player1Piece2 || killedPiece == self.Player1Piece3 || killedPiece == self.Player1Piece4) && self.movesRemainingBack != 1) || ((killedPiece == self.Player2Piece1 || killedPiece == self.Player2Piece2 || killedPiece == self.Player2Piece3 || killedPiece == self.Player2Piece4) && self.movesRemainingBack != 5) || ((killedPiece == self.Player3Piece1 || killedPiece == self.Player3Piece2 || killedPiece == self.Player3Piece3 || killedPiece == self.Player3Piece4) && self.movesRemainingBack != 9) || ((killedPiece == self.Player4Piece1 || killedPiece == self.Player4Piece2 || killedPiece == self.Player4Piece3 || killedPiece == self.Player4Piece4) && self.movesRemainingBack != 13) {
self.movesRemainingBack -= 1
let moveAction:SKAction = SKAction.move(to: (self.childNode(withName: String(self.movesRemainingBack))?.position)!, duration: 0.4)
moveAction.timingMode = .easeOut
let runAction:SKAction = SKAction.run({
if ((self.killedPiece == self.Player1Piece1 || self.killedPiece == self.Player1Piece2 || self.killedPiece == self.Player1Piece3 || self.killedPiece == self.Player1Piece4) && self.movesRemainingBack == 1) || ((self.killedPiece == self.Player2Piece1 || self.killedPiece == self.Player2Piece2 || self.killedPiece == self.Player2Piece3 || self.killedPiece == self.Player2Piece4) && self.movesRemainingBack == 5) || ((self.killedPiece == self.Player3Piece1 || self.killedPiece == self.Player3Piece2 || self.killedPiece == self.Player3Piece3 || self.killedPiece == self.Player3Piece4) && self.movesRemainingBack == 9) || ((self.killedPiece == self.Player4Piece1 || self.killedPiece == self.Player4Piece2 || self.killedPiece == self.Player4Piece3 || self.killedPiece == self.Player4Piece4) && self.movesRemainingBack == 13) {
self.setThePlayerSpaceBack(space: self.movesRemainingBack, Killed: self.killedPiece)
}
self.movesRemaining = self.movesRemaining - 1
self.moveBackPiece()
})
self.killedPiece.run(SKAction.sequence([moveAction, runAction]))
}
}
how can I solve it with GCD Or something else?
Thanks for your Time.
You have to use GCD group queues. It will work with async operations also. It's like Go In -> Go Out, Go In ->Go Out, At the end it will notify you , Here is the example
let queue = DispatchQueue(label: "com.your.text", attributes: .concurrent)
let group = DispatchGroup()
group.enter()
queue.async {
print("1st Operation")
Thread.sleep(forTimeInterval: 10)
print("1st Operatio finished")
group.leave()
}
group.enter()
queue.async {
print("2nd Operation")
Thread.sleep(forTimeInterval: 10)
print("2nd Operation finished")
group.leave()
}
group.notify(queue: .main) {
print("Finished")
}
It's quickly written here, so might be syntax error will come. I hope it helps you out on your issue.

Anyobject is not a subtype of NSLayoutConstraint

I am upgrading to Swift3, below code was working fine in Swift 2.3 but it is not working with Swift 3
let constraints: NSArray = contentView.constraints as NSArray
let indexOfConstraint = constraints.indexOfObject (passingTest: { (constraint, idx, stop) in
return ((constraint as AnyObject).firstItem as! UIView).tag == bubbleTag && (constraint.firstAttribute == NSLayoutAttribute.left || constraint.firstAttribute == NSLayoutAttribute.right)
})
I am getting following compiler error:
'(AnyObject)' is not a subtype of 'NSLayoutConstraint'
How can I fix this?
I think you might need something like this...
contentView.constraints.index(where: { constraint in
guard let firstItemView = constraint.firstItem as? UIView else {
return false
}
return firstItemView.tag == bubbleTag && (constraint.firstAttribute == .left || constraint.firstAttribute == .right)
})

Xcode 7 - How do I specify different 2x graphics for iPhone 5 and Iphone6

I am developing a game using SpriteKit. How do I specify a different 2x graphics for the iphone5 and iPhone6 since they both use the #2x slot in the asset catalog folder?
I have tried changing the scale mode and it doesn't seem to have any effect.
This solution work for Swift 2.x (below you can find the Swift 3.x code)
You could do:
struct ScreenSize
{
static let SCREEN_WIDTH = UIScreen.mainScreen().bounds.size.width
static let SCREEN_HEIGHT = UIScreen.mainScreen().bounds.size.height
static let SCREEN_MAX_LENGTH = max(ScreenSize.SCREEN_WIDTH, ScreenSize.SCREEN_HEIGHT)
static let SCREEN_MIN_LENGTH = min(ScreenSize.SCREEN_WIDTH, ScreenSize.SCREEN_HEIGHT)
}
struct DeviceType
{
static let IS_IPHONE = UIDevice.currentDevice().userInterfaceIdiom == .Phone
static let IS_IPHONE_4_OR_LESS = UIDevice.currentDevice().userInterfaceIdiom == .Phone && ScreenSize.SCREEN_MAX_LENGTH < 568.0
static let IS_IPHONE_5 = UIDevice.currentDevice().userInterfaceIdiom == .Phone && ScreenSize.SCREEN_MAX_LENGTH == 568.0
static let IS_IPHONE_6 = UIDevice.currentDevice().userInterfaceIdiom == .Phone && ScreenSize.SCREEN_MAX_LENGTH == 667.0
static let IS_IPHONE_6P = UIDevice.currentDevice().userInterfaceIdiom == .Phone && ScreenSize.SCREEN_MAX_LENGTH == 736.0
static let IS_IPAD = UIDevice.currentDevice().userInterfaceIdiom == .Pad && ScreenSize.SCREEN_MAX_LENGTH == 1024.0
static let IS_IPAD_PRO = UIDevice.currentDevice().userInterfaceIdiom == .Pad && ScreenSize.SCREEN_MAX_LENGTH == 1366.0
}
Swift 3
You could do:
struct ScreenSize
{
static let SCREEN_WIDTH = UIScreen.main.bounds.size.width
static let SCREEN_HEIGHT = UIScreen.main.bounds.size.height
static let SCREEN_MAX_LENGTH = max(ScreenSize.SCREEN_WIDTH, ScreenSize.SCREEN_HEIGHT)
static let SCREEN_MIN_LENGTH = min(ScreenSize.SCREEN_WIDTH, ScreenSize.SCREEN_HEIGHT)
}
struct DeviceType
{
static let IS_IPHONE = UIDevice.current.userInterfaceIdiom == .phone
static let IS_IPHONE_4_OR_LESS = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH < 568.0
static let IS_IPHONE_5 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 568.0
static let IS_IPHONE_6 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 667.0
static let IS_IPHONE_6P = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 736.0
static let IS_IPAD = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.SCREEN_MAX_LENGTH == 1024.0
static let IS_IPAD_PRO = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.SCREEN_MAX_LENGTH == 1366.0
}
Usage (equal for both Swift 2.x and Swift 3):
if DeviceType.IS_IPHONE_5 {
// do stuff for my iPhone 5
}

Problems contact between two SpriteNodes

I have a problem with my func contact because the second contact don't work (contact with Bonus and Vaisseau) but the two others contact don't work.
So this is my code :
The function :
func didBeginContact(contact: SKPhysicsContact) {
let PremierBody : SKPhysicsBody = contact.bodyA
let SecondBody : SKPhysicsBody = contact.bodyB
if ((PremierBody.categoryBitMask == PhysicsCategories.Meteorites) && (SecondBody.categoryBitMask == PhysicsCategories.Meteorites)) {
contactEntreMeteorites(PremierBody.node as! SKSpriteNode, Meteorites2: SecondBody.node as! SKSpriteNode)
}
else if ((PremierBody.categoryBitMask == PhysicsCategories.Bonus) && (SecondBody.categoryBitMask == PhysicsCategories.Vaisseau) ||
(PremierBody.categoryBitMask == PhysicsCategories.Vaisseau) && (SecondBody.categoryBitMask == PhysicsCategories.Bonus)){
gameOver(PremierBody.node as! SKSpriteNode, Vaisseau: SecondBody.node as! SKSpriteNode)
print("CONTACT")
}
else if ((PremierBody.categoryBitMask == PhysicsCategories.Meteorites) && (SecondBody.categoryBitMask == PhysicsCategories.Vaisseau) ||
(PremierBody.categoryBitMask == PhysicsCategories.Vaisseau) && (SecondBody.categoryBitMask == PhysicsCategories.Meteorites)){
gameOver(PremierBody.node as! SKSpriteNode, Vaisseau: SecondBody.node as! SKSpriteNode)
print("Couco")
}
}
And this is my Physics categories :
struct PhysicsCategories {
static let Meteorites : UInt32 = 1
static let Bonus : UInt32 = 2
static let Vaisseau : UInt32 = 5
}
This in my func DidMoveToView :
Vaisseau = SKSpriteNode(texture: Vaisseau1)
Vaisseau.position = CGPointMake(self.frame.size.width / 2, self.frame.size.height / 2)
Vaisseau.physicsBody = SKPhysicsBody(rectangleOfSize: Vaisseau.size)
Vaisseau.physicsBody?.affectedByGravity = false
Vaisseau.physicsBody?.categoryBitMask = PhysicsCategories.Vaisseau
Vaisseau.physicsBody?.contactTestBitMask = PhysicsCategories.Bonus
Vaisseau.physicsBody?.contactTestBitMask = PhysicsCategories.Meteorites
Vaisseau.physicsBody?.dynamic = false
Vaisseau.setScale(0.08)
self.addChild(Vaisseau)
And i create my SpriteNode Bonus in this function :
func ApparitionBonus() {
let BonusSprite = SKSpriteNode(imageNamed: "Bonus.png")
var BonusApparitionX = UInt32(self.frame.size.width)
var BonusApparitionY = UInt32(self.frame.size.height)
BonusApparitionX = arc4random() % BonusApparitionX
BonusApparitionY = arc4random() % BonusApparitionY
BonusSprite.position = CGPointMake(CGFloat(BonusApparitionX),CGFloat(BonusApparitionY))
BonusSprite.setScale(0.8)
BonusSprite.physicsBody = SKPhysicsBody(circleOfRadius: 20)
BonusSprite.physicsBody?.affectedByGravity = false
BonusSprite.physicsBody?.categoryBitMask = PhysicsCategories.Bonus
BonusSprite.physicsBody?.contactTestBitMask = PhysicsCategories.Vaisseau
BonusSprite.physicsBody?.dynamic = false
self.addChild(BonusSprite)
let RotationBonus = SKAction.rotateByAngle(CGFloat(M_PI), duration: 3)
let wait = SKAction.waitForDuration(3)
let actionFini = SKAction.removeFromParent()
BonusSprite.runAction(SKAction.sequence([RotationBonus, wait, actionFini]))
BonusSprite.runAction(SKAction.repeatActionForever(RotationBonus))
}
In your didMoveToView, when you call:
Vaisseau.physicsBody?.contactTestBitMask = PhysicsCategories.Bonus
Vaisseau.physicsBody?.contactTestBitMask = PhysicsCategories.Meteorites
You set the contactTestBitMask to one category, and then another. You need to bitwise or them together. Something like:
Vaisseau.physicsBody?.contactTestBitMask = PhysicsCategories.Bonus | PhysicsCategories.Meteorites
This will combine the two bit masks, which will allow it to contact both the Bonus and Meteorites.
If you don't want your sprites to collide, set the collisionBitMask to 0x0 (or however you want to represent 0):
Vaisseau.physicsBody?.collisionBitMask = 0x0

iOS How to detect iPhone X, iPhone 6 plus, iPhone 6, iPhone 5, iPhone 4 by macro?

How to detect device model by macro?
i had using something like this but the result on the simulator alway IS_IPHONE_5
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_IPHONE_5 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 568.0)
#define IS_IPHONE_6 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 667.0)
#define IS_IPHONE_6PLUS (IS_IPHONE && [[UIScreen mainScreen] nativeScale] == 3.0f)
#define IS_IPHONE_6_PLUS (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 736.0)
#define IS_RETINA ([[UIScreen mainScreen] scale] == 2.0)
Swift
import UIKit
public enum DisplayType {
case unknown
case iphone4
case iphone5
case iphone6
case iphone6plus
static let iphone7 = iphone6
static let iphone7plus = iphone6plus
case iphoneX
}
public final class Display {
class var width:CGFloat { return UIScreen.main.bounds.size.width }
class var height:CGFloat { return UIScreen.main.bounds.size.height }
class var maxLength:CGFloat { return max(width, height) }
class var minLength:CGFloat { return min(width, height) }
class var zoomed:Bool { return UIScreen.main.nativeScale >= UIScreen.main.scale }
class var retina:Bool { return UIScreen.main.scale >= 2.0 }
class var phone:Bool { return UIDevice.current.userInterfaceIdiom == .phone }
class var pad:Bool { return UIDevice.current.userInterfaceIdiom == .pad }
class var carplay:Bool { return UIDevice.current.userInterfaceIdiom == .carPlay }
class var tv:Bool { return UIDevice.current.userInterfaceIdiom == .tv }
class var typeIsLike:DisplayType {
if phone && maxLength < 568 {
return .iphone4
}
else if phone && maxLength == 568 {
return .iphone5
}
else if phone && maxLength == 667 {
return .iphone6
}
else if phone && maxLength == 736 {
return .iphone6plus
}
else if phone && maxLength == 812 {
return .iphoneX
}
return .unknown
}
}
See it in action
https://gist.github.com/hfossli/bc93d924649de881ee2882457f14e346
Note: If e.g. iPhone 6 is in zoomed mode the UI is a zoomed up version of iPhone 5. These functions is not determining device type, but display mode thus iPhone 5 is the desired result in this example.
Objective-C
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_RETINA ([[UIScreen mainScreen] scale] >= 2.0)
#define SCREEN_WIDTH ([[UIScreen mainScreen] bounds].size.width)
#define SCREEN_HEIGHT ([[UIScreen mainScreen] bounds].size.height)
#define SCREEN_MAX_LENGTH (MAX(SCREEN_WIDTH, SCREEN_HEIGHT))
#define SCREEN_MIN_LENGTH (MIN(SCREEN_WIDTH, SCREEN_HEIGHT))
#define IS_ZOOMED (IS_IPHONE && SCREEN_MAX_LENGTH == 736.0)
#define IS_IPHONE_4_OR_LESS (IS_IPHONE && SCREEN_MAX_LENGTH < 568.0)
#define IS_IPHONE_5 (IS_IPHONE && SCREEN_MAX_LENGTH == 568.0)
#define IS_IPHONE_6 (IS_IPHONE && SCREEN_MAX_LENGTH == 667.0)
#define IS_IPHONE_6P (IS_IPHONE && SCREEN_MAX_LENGTH == 736.0)
#define IS_IPHONE_X (IS_IPHONE && SCREEN_MAX_LENGTH == 812.0)
Usage: http://pastie.org/9687735
Note: If e.g. iPhone 6 is in zoomed mode the UI is a zoomed up version of iPhone 5. These functions is not determining device type, but display mode thus iPhone 5 is the desired result in this example.
For Swift:
struct ScreenSize
{
static let SCREEN_WIDTH = UIScreen.main.bounds.size.width
static let SCREEN_HEIGHT = UIScreen.main.bounds.size.height
static let SCREEN_MAX_LENGTH = max(ScreenSize.SCREEN_WIDTH, ScreenSize.SCREEN_HEIGHT)
static let SCREEN_MIN_LENGTH = min(ScreenSize.SCREEN_WIDTH, ScreenSize.SCREEN_HEIGHT)
}
struct DeviceType
{
static let IS_IPHONE_4_OR_LESS = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH < 568.0
static let IS_IPHONE_5 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 568.0
static let IS_IPHONE_6 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 667.0
static let IS_IPHONE_6P = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 736.0
}
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) // iPhone and iPod touch style UI
#define IS_IPHONE_5_IOS7 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 568.0f)
#define IS_IPHONE_6_IOS7 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 667.0f)
#define IS_IPHONE_6P_IOS7 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 736.0f)
#define IS_IPHONE_4_AND_OLDER_IOS7 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height < 568.0f)
#define IS_IPHONE_5_IOS8 (IS_IPHONE && ([[UIScreen mainScreen] nativeBounds].size.height/[[UIScreen mainScreen] nativeScale]) == 568.0f)
#define IS_IPHONE_6_IOS8 (IS_IPHONE && ([[UIScreen mainScreen] nativeBounds].size.height/[[UIScreen mainScreen] nativeScale]) == 667.0f)
#define IS_IPHONE_6P_IOS8 (IS_IPHONE && ([[UIScreen mainScreen] nativeBounds].size.height/[[UIScreen mainScreen] nativeScale]) == 736.0f)
#define IS_IPHONE_4_AND_OLDER_IOS8 (IS_IPHONE && ([[UIScreen mainScreen] nativeBounds].size.height/[[UIScreen mainScreen] nativeScale]) < 568.0f)
#define IS_IPHONE_5 ( ( [ [ UIScreen mainScreen ] respondsToSelector: #selector( nativeBounds ) ] ) ? IS_IPHONE_5_IOS8 : IS_IPHONE_5_IOS7 )
#define IS_IPHONE_6 ( ( [ [ UIScreen mainScreen ] respondsToSelector: #selector( nativeBounds ) ] ) ? IS_IPHONE_6_IOS8 : IS_IPHONE_6_IOS7 )
#define IS_IPHONE_6P ( ( [ [ UIScreen mainScreen ] respondsToSelector: #selector( nativeBounds ) ] ) ? IS_IPHONE_6P_IOS8 : IS_IPHONE_6P_IOS7 )
#define IS_IPHONE_4_AND_OLDER ( ( [ [ UIScreen mainScreen ] respondsToSelector: #selector( nativeBounds ) ] ) ? IS_IPHONE_4_AND_OLDER_IOS8 : IS_IPHONE_4_AND_OLDER_IOS7 )
public extension UIDevice {
var iPhone: Bool {
return UIDevice().userInterfaceIdiom == .Phone
}
enum ScreenType: String {
case iPhone4
case iPhone5
case iPhone6
case iPhone6Plus
case Unknown
}
var screenType: ScreenType {
guard iPhone else { return .Unknown}
switch UIScreen.mainScreen().nativeBounds.height {
case 960:
return .iPhone4
case 1136:
return .iPhone5
case 1334:
return .iPhone6
case 1920: //fallthrough
return .iPhone6Plus
case 2208:
return .iPhone6Plus
default:
return .Unknown
}
}
}
I use a class that pulls actual system info. Just have to make sure all device types are up to date.
#import "Macros.h"
#implementation Macros
+ (BOOL)IS_IPHONE_6_PLUS {
return [[self deviceType] isEqualToString:#"iPhone 6 Plus"] || [[self deviceType] isEqualToString:#"iPhone 6S Plus"];
}
+ (BOOL)IS_IPHONE_6 {
return [[self deviceType] isEqualToString:#"iPhone 6"] || [[self deviceType] isEqualToString:#"iPhone 6S"];
}
+ (BOOL)IS_SIMULATOR {
return [[self deviceType] isEqualToString:#"32-bit Simulator"]
|| [[self deviceType] isEqualToString:#"64-bit Simulator"];
}
+ (BOOL)IS_IPHONE_5 {
NSString *device = [self deviceType];
BOOL result = [device isEqualToString:#"iPhone 5(GSM)"] || [device isEqualToString:#"iPhone 5(GSM+CDMA)"]
|| [device isEqualToString:#"iPhone 5C(GSM)"] || [device isEqualToString:#"iPhone 5C(GSM+CDMA)"]
|| [device isEqualToString:#"iPhone 5S(GSM)"] || [device isEqualToString:#"iPhone 5S(GSM+CDMA)"];
return result;
}
/*
#"i386" on 32-bit Simulator
#"x86_64" on 64-bit Simulator
#"iPod1,1" on iPod Touch
#"iPod2,1" on iPod Touch Second Generation
#"iPod3,1" on iPod Touch Third Generation
#"iPod4,1" on iPod Touch Fourth Generation
#"iPod5,1" on iPod Touch Fifth Generation
#"iPhone1,1" on iPhone
#"iPhone1,2" on iPhone 3G
#"iPhone2,1" on iPhone 3GS
#"iPad1,1" on iPad
#"iPad2,1" on iPad 2
#"iPad3,1" on 3rd Generation iPad
#"iPad3,2": on iPad 3(GSM+CDMA)
#"iPad3,3": on iPad 3(GSM)
#"iPad3,4": on iPad 4(WiFi)
#"iPad3,5": on iPad 4(GSM)
#"iPad3,6": on iPad 4(GSM+CDMA)
#"iPhone3,1" on iPhone 4
#"iPhone4,1" on iPhone 4S
#"iPad3,4" on 4th Generation iPad
#"iPad2,5" on iPad Mini
#"iPhone5,1" on iPhone 5(GSM)
#"iPhone5,2" on iPhone 5(GSM+CDMA)
#"iPhone5,3 on iPhone 5c(GSM)
#"iPhone5,4" on iPhone 5c(GSM+CDMA)
#"iPhone6,1" on iPhone 5s(GSM)
#"iPhone6,2" on iPhone 5s(GSM+CDMA)
#"iPhone7,1" on iPhone 6 Plus
#"iPhone7,2" on iPhone 6
#"iPhone8,1" on iPhone 6
#"iPhone8,2" on iPhone 6 Plus ...Yes Apple switched the order...
*/
+ (NSString *)deviceType {
struct utsname systemInfo;
uname(&systemInfo);
NSString *result = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
// https://www.theiphonewiki.com/wiki/Models
NSDictionary *matches = #{
#"i386" : #"32-bit Simulator",
#"x86_64" : #"64-bit Simulator",
#"iPod1,1" : #"iPod Touch",
#"iPod2,1" : #"iPod Touch Second Generation",
#"iPod3,1" : #"iPod Touch Third Generation",
#"iPod4,1" : #"iPod Touch Fourth Generation",
#"iPod5,1" : #"iPod Touch Fifth Generation",
#"iPad1,1" : #"iPad",
#"iPad2,1" : #"iPad 2",
#"iPad2,2" : #"iPad 2",
#"iPad2,3" : #"iPad 2",
#"iPad2,4" : #"iPad 2",
#"iPad2,5" : #"iPad Mini",
#"iPad2,6" : #"iPad Mini",
#"iPad2,7" : #"iPad Mini",
#"iPad3,1" : #"iPad 3",
#"iPad3,2" : #"iPad 3(GSM+CDMA)",
#"iPad3,3" : #"iPad 3(GSM)",
#"iPad3,4" : #"iPad 4(WiFi)",
#"iPad3,5" : #"iPad 4(GSM)",
#"iPad3,6" : #"iPad 4(GSM+CDMA)",
#"iPad4,1" : #"iPad Air",
#"iPad4,2" : #"iPad Air",
#"iPad4,3" : #"iPad Air",
#"iPad4,4" : #"iPad Mini 2",
#"iPad4,5" : #"iPad Mini 2",
#"iPad4,6" : #"iPad Mini 2",
#"iPad4,7" : #"iPad Mini 3",
#"iPad4,8" : #"iPad Mini 3",
#"iPad4,9" : #"iPad Mini 3",
#"iPad5,1" : #"iPad Mini 4",
#"iPad5,2" : #"iPad Mini 4",
#"iPad5,3" : #"iPad Air 2",
#"iPad5,4" : #"iPad Air 2",
#"iPad6,3" : #"iPad Pro (9.7in)",
#"iPad6,4" : #"iPad Pro (9.7in)",
#"iPad6,7" : #"iPad Pro (12.9in)",
#"iPad6,8" : #"iPad Pro (12.9in)",
#"iPhone1,1" : #"iPhone",
#"iPhone1,2" : #"iPhone 3G",
#"iPhone2,1" : #"iPhone 3GS",
#"iPhone3,1" : #"iPhone 4",
#"iPhone3,3" : #"iPhone 4",
#"iPhone4,1" : #"iPhone 4S",
#"iPhone5,1" : #"iPhone 5(GSM)",
#"iPhone5,2" : #"iPhone 5(GSM+CDMA)",
#"iPhone5,3" : #"iPhone 5C(GSM)",
#"iPhone5,4" : #"iPhone 5C(GSM+CDMA)",
#"iPhone6,1" : #"iPhone 5S(GSM)",
#"iPhone6,2" : #"iPhone 5S(GSM+CDMA)",
#"iPhone7,1" : #"iPhone 6 Plus",
#"iPhone7,2" : #"iPhone 6",
#"iPhone8,1" : #"iPhone 6S",
#"iPhone8,2" : #"iPhone 6S Plus",
#"iPhone8,4" : #"iPhone SE",
#"iPhone9,1" : #"iPhone 7",
#"iPhone9,3" : #"iPhone 7",
#"iPhone9,2" : #"iPhone 7 Plus",
#"iPhone9,4" : #"iPhone 7 Plus",
};
if (matches[result]) {
return matches[result];
} else {
return result;
}
}
#end
I can confirm the bug goes away when you set a Launch Screen.
I kept my launch images, and added MainStoryboard to Launch Screen and the simulator recognized the devices correctly.
It's better not to bind your code with device types. This will lead to inflexible convoluted one. Apple wants you to think about sizes not devices. In case you need to have special sizes for devices larger than iPhone 5 such as image or font sizes, I would recommend to create a normalize class with a multiplier that grows your base size by a certain percent based on the relation between the iPhone 5 screen width and the current device size.
let BaseWidth : CGFloat = 320
class Normalizer: NSObject {
//scale value proportional to the screen width
class func normalize(value:CGFloat,multiplier : CGFloat = 1,maxDelta:CGFloat = 1024) -> CGFloat{
let screenWidth = UIScreen.mainScreen().bounds.size.width
let percent = (screenWidth - BaseWidth)/screenWidth
let normalizedValue = value * (1 + percent) * multiplier
return min(normalizedValue, value + maxDelta)//capped by a max value if needed
}
}
So in your code you will do something like that:
value = Normalizer.normalize(30)
UIDeivce extension with Swift 3+ syntax.
public extension UIDevice {
var iPhone: Bool {
return UIDevice().userInterfaceIdiom == .phone
}
enum ScreenType: String {
case iPhone4
case iPhone5
case iPhone6
case iPhone6Plus
case iPhoneX
case Unknown
}
var screenType: ScreenType {
guard iPhone else { return .Unknown}
switch UIScreen.main.nativeBounds.height {
case 960:
return .iPhone4
case 1136:
return .iPhone5
case 1334:
return .iPhone6
case 2208, 1920:
return .iPhone6Plus
case 2436:
return .iPhoneX
default:
return .Unknown
}
}
}
Sample usage:
switch UIDevice().screenType {
case .iPhone4, .iPhone5:
// Code for iPhone 4 & iPhone 5
break
case .iPhone6:
// Code for iPhone 6 & iPhone 7
break
case .iPhone6Plus:
// Code for iPhone 6 Plus & iPhone 7 Plus
break
case .iPhoneX:
// Code for iPhone X
break
default:
break
}
Original answer: https://stackoverflow.com/a/36479017/3659227
Update Xcode 13 / Swift 5.5:
enum UIUserInterfaceIdiom : Int
{
case Unspecified
case Phone
case Pad
}
struct ScreenSize
{
static let SCREEN_WIDTH = UIScreen.main.bounds.size.width
static let SCREEN_HEIGHT = UIScreen.main.bounds.size.height
static let SCREEN_MAX_LENGTH = max(ScreenSize.SCREEN_WIDTH, ScreenSize.SCREEN_HEIGHT)
static let SCREEN_MIN_LENGTH = min(ScreenSize.SCREEN_WIDTH, ScreenSize.SCREEN_HEIGHT)
}
struct DeviceType
{
static let IS_IPHONE_4_OR_LESS = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH < 568.0
static let IS_IPHONE_5 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 568.0
static let IS_IPHONE_6_8 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 667.0
static let IS_IPHONE_6_8P = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 736.0
static let IS_IPHONE_X = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 812.0
static let IS_IPHONE_11_PRO = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 812.0
static let IS_IPHONE_12_13_MINI = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 812.0
static let IS_IPHONE_12 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 844.0
static let IS_IPHONE_12_PRO = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 844.0
static let IS_IPHONE_13 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 844.0
static let IS_IPHONE_XR_SMAX = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 896.0
static let IS_IPHONE_XS_MAX = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 896.0
static let IS_IPHONE_11 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 896.0
static let IS_IPHONE_11_PRO_MAX = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 896.0
static let IS_IPHONE_12_13_PRO_MAX = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 926.0
static let IS_IPAD = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.SCREEN_MAX_LENGTH == 1024.0
static let IS_IPAD_MINI_4 = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.SCREEN_MAX_LENGTH == 1024.0
static let IS_IPAD_PRO9 = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.SCREEN_MAX_LENGTH == 1024.0
static let IS_IPAD_10 = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.SCREEN_MAX_LENGTH == 1080.0
static let IS_IPAD_PRO10 = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.SCREEN_MAX_LENGTH == 1112.0
static let IS_IPAD_PRO11 = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.SCREEN_MAX_LENGTH == 1194.0
static let IS_IPAD_PRO12 = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.SCREEN_MAX_LENGTH == 1366.0
static let IS_IPAD_ALL = UIDevice.current.userInterfaceIdiom == .pad
static let IS_IPHONE_NOTCH_DEVICE = (UIDevice.current.userInterfaceIdiom == .phone) && (ScreenSize.SCREEN_MAX_LENGTH == 896.0 || ScreenSize.SCREEN_MAX_LENGTH == 812.0)
}
//struct DeviceDisplay
//{
// static let isZoomed:Bool = UIScreen.main.nativeScale >= UIScreen.main.scale
//}
struct Version{
static let SYS_VERSION_FLOAT = (UIDevice.current.systemVersion as NSString).floatValue
static let iOS9 = (Version.SYS_VERSION_FLOAT >= 9.0 && Version.SYS_VERSION_FLOAT < 10.0)
static let iOS10 = (Version.SYS_VERSION_FLOAT >= 10.0 && Version.SYS_VERSION_FLOAT < 11.0)
static let iOS11 = (Version.SYS_VERSION_FLOAT >= 11.0 && Version.SYS_VERSION_FLOAT < 12.0)
static let iOS12 = (Version.SYS_VERSION_FLOAT >= 12.0 && Version.SYS_VERSION_FLOAT < 13.0)
static let iOS13 = (Version.SYS_VERSION_FLOAT >= 13.0 && Version.SYS_VERSION_FLOAT < 14.0)
static let iOS14 = (Version.SYS_VERSION_FLOAT >= 14.0 && Version.SYS_VERSION_FLOAT < 15.0)
static let iOS15 = (Version.SYS_VERSION_FLOAT >= 15.0)
}
struct VersionAndNewer {
static let iOS9 = (Version.SYS_VERSION_FLOAT >= 9.0)
static let iOS10 = (Version.SYS_VERSION_FLOAT >= 10.0)
static let iOS11 = (Version.SYS_VERSION_FLOAT >= 11.0)
static let iOS12 = (Version.SYS_VERSION_FLOAT >= 12.0)
static let iOS13 = (Version.SYS_VERSION_FLOAT >= 13.0)
static let iOS14 = (Version.SYS_VERSION_FLOAT >= 14.0)
static let iOS15 = (Version.SYS_VERSION_FLOAT >= 15.0)
}
Update Xcode 11 / Swift 5.1:
enum UIUserInterfaceIdiom : Int
{
case Unspecified
case Phone
case Pad
}
struct ScreenSize
{
static let SCREEN_WIDTH = UIScreen.main.bounds.size.width
static let SCREEN_HEIGHT = UIScreen.main.bounds.size.height
static let SCREEN_MAX_LENGTH = max(ScreenSize.SCREEN_WIDTH, ScreenSize.SCREEN_HEIGHT)
static let SCREEN_MIN_LENGTH = min(ScreenSize.SCREEN_WIDTH, ScreenSize.SCREEN_HEIGHT)
}
struct DeviceType
{
static let IS_IPHONE_4_OR_LESS = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH < 568.0
static let IS_IPHONE_5 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 568.0
static let IS_IPHONE_6_8 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 667.0
static let IS_IPHONE_6_8P = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 736.0
static let IS_IPHONE_X = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 812.0
static let IS_IPHONE_11_PRO = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 812.0
static let IS_IPHONE_XR_SMAX = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 896.0
static let IS_IPHONE_XS_MAX = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 896.0
static let IS_IPHONE_11 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 896.0
static let IS_IPHONE_11_PRO_MAX = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 896.0
static let IS_IPAD = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.SCREEN_MAX_LENGTH == 1024.0
static let IS_IPAD_PRO10 = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.SCREEN_MAX_LENGTH == 1112.0
static let IS_IPAD_PRO12 = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.SCREEN_MAX_LENGTH == 1366.0
static let IS_IPAD_ALL = UIDevice.current.userInterfaceIdiom == .pad
static let IS_IPHONE_NOTCH_DEVICE = (UIDevice.current.userInterfaceIdiom == .phone) && (ScreenSize.SCREEN_MAX_LENGTH == 896.0 || ScreenSize.SCREEN_MAX_LENGTH == 812.0)
}
struct Version{
static let SYS_VERSION_FLOAT = (UIDevice.current.systemVersion as NSString).floatValue
static let iOS9 = (Version.SYS_VERSION_FLOAT >= 9.0 && Version.SYS_VERSION_FLOAT < 10.0)
static let iOS10 = (Version.SYS_VERSION_FLOAT >= 10.0 && Version.SYS_VERSION_FLOAT < 11.0)
static let iOS11 = (Version.SYS_VERSION_FLOAT >= 11.0 && Version.SYS_VERSION_FLOAT < 12.0)
static let iOS12 = (Version.SYS_VERSION_FLOAT >= 12.0 && Version.SYS_VERSION_FLOAT < 13.0)
static let iOS13 = (Version.SYS_VERSION_FLOAT >= 13.0)
}
struct VersionAndNewer {
static let iOS9 = (Version.SYS_VERSION_FLOAT >= 9.0)
static let iOS10 = (Version.SYS_VERSION_FLOAT >= 10.0)
static let iOS11 = (Version.SYS_VERSION_FLOAT >= 11.0)
static let iOS12 = (Version.SYS_VERSION_FLOAT >= 12.0)
static let iOS13 = (Version.SYS_VERSION_FLOAT >= 13.0)
}
Hi i updated to Xcode10 / Swift 4.2 and the new sizes for IPhone XS / XSMAX /XR
with detection of Notch-IPhones.
Hope this helps someone.
enum UIUserInterfaceIdiom : Int
{
case Unspecified
case Phone
case Pad
}
struct ScreenSize
{
static let SCREEN_WIDTH = UIScreen.main.bounds.size.width
static let SCREEN_HEIGHT = UIScreen.main.bounds.size.height
static let SCREEN_MAX_LENGTH = max(ScreenSize.SCREEN_WIDTH, ScreenSize.SCREEN_HEIGHT)
static let SCREEN_MIN_LENGTH = min(ScreenSize.SCREEN_WIDTH, ScreenSize.SCREEN_HEIGHT)
}
struct DeviceType
{
static let IS_IPHONE_4_OR_LESS = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH < 568.0
static let IS_IPHONE_5 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 568.0
static let IS_IPHONE_6_8 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 667.0
static let IS_IPHONE_6_8P = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 736.0
static let IS_IPHONE_X = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 812.0
static let IS_IPHONE_XR_SMAX = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 896.0
static let IS_IPAD = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.SCREEN_MAX_LENGTH == 1024.0
static let IS_IPAD_PRO10 = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.SCREEN_MAX_LENGTH == 1112.0
static let IS_IPAD_PRO12 = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.SCREEN_MAX_LENGTH == 1366.0
static let IS_IPHONE_NOTCH_DEVICE = (UIDevice.current.userInterfaceIdiom == .phone) && (ScreenSize.SCREEN_MAX_LENGTH == 896.0 || ScreenSize.SCREEN_MAX_LENGTH == 812.0)
}
struct Version{
static let SYS_VERSION_FLOAT = (UIDevice.current.systemVersion as NSString).floatValue
static let iOS9 = (Version.SYS_VERSION_FLOAT >= 9.0 && Version.SYS_VERSION_FLOAT < 10.0)
static let iOS10 = (Version.SYS_VERSION_FLOAT >= 10.0 && Version.SYS_VERSION_FLOAT < 11.0)
static let iOS11 = (Version.SYS_VERSION_FLOAT >= 11.0 && Version.SYS_VERSION_FLOAT < 12.0)
static let iOS12 = (Version.SYS_VERSION_FLOAT >= 12.0)
}
struct VersionAndNewer {
static let iOS9 = (Version.SYS_VERSION_FLOAT >= 9.0)
static let iOS10 = (Version.SYS_VERSION_FLOAT >= 10.0)
static let iOS11 = (Version.SYS_VERSION_FLOAT >= 11.0)
static let iOS12 = (Version.SYS_VERSION_FLOAT >= 12.0)
}
I encountered the problem while migrating from an iOS 7 project to a iOS 8 project, since I didn't add a launch screen scene to my project.
In this case the screen size for iPhone 6 and 6+ are as iPhone 5.
See from apple documentation; You use a launch XIB or storyboard file to indicate that your app runs on iPhone 6 Plus or iPhone 6.
//Device Type enum
enum DeviceType: Int {
//Apple UnknownDevices
case UnknownDevice = 0
//Simulator
case Simulator
//Apple Air pods
case AppleAirPods
//Apple TV
case AppleTV2G
case AppleTV3G
case AppleTV4G
case AppleTV4K
//Apple Watch
case AppleWatch
case AppleWatchSeries1
case AppleWatchSeries2
case AppleWatchSeries3
//Apple Home Pods
case AppleHomePods
//Apple iPad
case AppleIpad
case AppleIpad2
case AppleIpad3
case AppleIpad4
case AppleIpadAir
case AppleIpadAir2
case AppleIpadPro_12_9
case AppleIpadPro_9_7
case AppleIpad5
case AppleIpadPro_12_9_Gen_2
case AppleIpadPro_10_5
case AppleIpadMini
case AppleIpadMini2
case AppleIpadMini3
case AppleIpadMini4
//Apple iPhone
case AppleIphone
case AppleIphone3G
case AppleIphone3GS
case AppleIphone4
case AppleIphone4S
case AppleIphone5
case AppleIphone5C
case AppleIphone5S
case AppleIphone6
case AppleIphone6P
case AppleIphone6S
case AppleIphone6SP
case AppleIphoneSE
case AppleIphone7
case AppleIphone7P
case AppleIphone8
case AppleIphone8P
case AppleIphoneX
//Apple iPod touch
case AppleIpodTouch
case AppleIpodTouch2G
case AppleIpodTouch3G
case AppleIpodTouch4G
case AppleIpodTouch5G
case AppleIpodTouch6G
}
// Method for device type
func getDeviceType() -> DeviceType{
var systemInfo = utsname()
uname(&systemInfo)
let machineMirror = Mirror(reflecting: systemInfo.machine)
let identifier = machineMirror.children.reduce("") { identifier, element in
guard let value = element.value as? Int8, value != 0 else { return identifier }
return identifier + String(UnicodeScalar(UInt8(value)))
}
switch identifier {
//Simulator
case "i386","x86_64": return .Simulator
//Apple Air Pods
case "AirPods1,1": return .AppleAirPods
//Apple TV
case "AppleTV2,1": return .AppleTV2G
case "AppleTV3,1", "AppleTV3,2": return .AppleTV3G
case "AppleTV5,3": return .AppleTV4G
case "AppleTV6,2": return .AppleTV4K
//Apple Watch
case "Watch1,1", "Watch1,2": return .AppleWatch
case "Watch2,6", "Watch2,7": return .AppleWatchSeries1
case "Watch2,3", "Watch2,4": return .AppleWatchSeries2
case "Watch3,1", "Watch3,2", "Watch3,3", "Watch3,4": return .AppleWatchSeries3
// Apple HomePods
case "AudioAccessory1,1": return .AppleHomePods
//Apple iPad
case "iPad1,1": return .AppleIpad
case "iPad2,1", "iPad2,2", "iPad2,3", "iPad2,4": return .AppleIpad2
case "iPad3,1", "iPad3,2", "iPad3,3": return .AppleIpad3
case "iPad3,4", "iPad3,5", "iPad3,6": return .AppleIpad4
case "iPad4,1", "iPad4,2", "iPad4,3": return .AppleIpadAir
case "iPad5,3", "iPad5,4": return .AppleIpadAir2
case "iPad6,7", "iPad6,8": return .AppleIpadPro_12_9
case "iPad6,3", "iPad6,4": return .AppleIpadPro_9_7
case "iPad6,11", "iPad6,12": return .AppleIpad5
case "iPad7,1", "iPad7,2" : return .AppleIpadPro_12_9_Gen_2
case "iPad7,3", "iPad7,4" : return .AppleIpadPro_10_5
case "iPad2,5", "iPad2,6", "iPad2,7": return .AppleIpadMini
case "iPad4,4", "iPad4,5", "iPad4,6": return .AppleIpadMini2
case "iPad4,7", "iPad4,8", "iPad4,9": return .AppleIpadMini3
case "iPad5,1", "iPad5,2": return .AppleIpadMini4
//Apple iPhone
case "iPhone1,1": return .AppleIphone
case "iPhone1,2": return .AppleIphone3G
case "iPhone2,1": return .AppleIphone3GS
case "iPhone3,1", "iPhone3,2", "iPhone3,3": return .AppleIphone4
case "iPhone4,1": return .AppleIphone4S
case "iPhone5,1", "iPhone5,2": return .AppleIphone5
case "iPhone5,3", "iPhone5,4": return .AppleIphone5C
case "iPhone6,1", "iPhone6,2": return .AppleIphone5S
case "iPhone7,2": return .AppleIphone6
case "iPhone7,1": return .AppleIphone6P
case "iPhone8,1": return .AppleIphone6S
case "iPhone8,2": return .AppleIphone6SP
case "iPhone8,4": return .AppleIphoneSE
case "iPhone9,1", "iPhone9,3": return .AppleIphone7
case "iPhone9,2", "iPhone9,4": return .AppleIphone7P
case "iPhone10,1", "iPhone10,4": return .AppleIphone8
case "iPhone10,2", "iPhone10,5": return .AppleIphone8P
case "iPhone10,3", "iPhone10,6": return .AppleIphoneX
//Apple iPod touch
case "iPod1,1": return .AppleIpodTouch
case "iPod2,1": return .AppleIpodTouch2G
case "iPod3,1": return .AppleIpodTouch3G
case "iPod4,1": return .AppleIpodTouch4G
case "iPod5,1": return .AppleIpodTouch5G
case "iPod7,1": return .AppleIpodTouch6G
default:
return .UnknownDevice
}
}
For plus, you have to check zoom too
struct DeviceType
{
static let IS_IPHONE = (UIDevice.current.userInterfaceIdiom == .phone)
static let IS_IPHONE_4_OR_LESS = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH < 568.0
static let IS_IPHONE_5 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 568.0
static let IS_IPHONE_6_7 = (UIDevice.current.userInterfaceIdiom == .phone) && (ScreenSize.SCREEN_MAX_LENGTH == 667.0) && (UIScreen.main.nativeScale >= UIScreen.main.scale)
private static let IS_STANDARD_IPHONE_6P_7P = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 736.0
private static let IS_ZOOMED_IPHONE_6P_7P = (UIDevice.current.userInterfaceIdiom == .phone) && (ScreenSize.SCREEN_MAX_LENGTH == 667.0) && (UIScreen.main.nativeScale < UIScreen.main.scale)
static let IS_IPHONE_6P_7P = IS_STANDARD_IPHONE_6P_7P || IS_ZOOMED_IPHONE_6P_7P
}
import Foundation
import UIKit
public enum IADisplayType {
// unknow device
case unspecified
// iPhone
case unknowiPhone
case iPhone3GS
case iPhone4
static let iPhone4s = iPhone5
case iPhone5
static let iPhone5s = iPhone5
static let iPhoneSE = iPhone5
case iPhone6
case iPhone6Plus
static let iPhone6s = iPhone6
static let iPhone6sPlus = iPhone6Plus
static let iPhone7 = iPhone6
static let iPhone7Plus = iPhone6Plus
static let iPhone8 = iPhone6
static let iPhone8Plus = iPhone6Plus
case iPhoneX
// iPad
case unknowiPad
case iPad79
static let iPad97 = iPad79
case iPad105
case iPad129
// Apple CarPlay
case carPlay
// Apple TV
case tv
}
public final class IADisplayManager {
// MARK: - public interface
// singleton
static var shared: IADisplayManager {
get {
return IADisplayManager()
}
}
// get current device type
public var currentType: IADisplayType {
get {
return calCurrentType()
}
}
// device current Native Resolution
public var nativeResolution: CGSize {
get {
return UIScreen.main.nativeBounds.size
}
}
// device current Native Scale Factor
public var nativeScaleFactor: CGFloat {
get {
return UIScreen.main.nativeScale
}
}
// device current Interface Idiom
public var interfaceIdiom: UIUserInterfaceIdiom {
get {
return UIDevice().userInterfaceIdiom
}
}
fileprivate init() {}
// MARK: - private interface
fileprivate func calCurrentType() -> IADisplayType {
typealias Type = IADisplayType
// unknown device
if interfaceIdiom == .unspecified { return Type.unspecified }
// iPhone && iPod Touch
else if interfaceIdiom == .phone {
if nativeScaleFactor == 1.0 && nativeResolution == CGSize(width: 320, height: 480) { return Type.iPhone3GS }
else if nativeScaleFactor == 2.0 && nativeResolution == CGSize(width: 640, height: 960) { return Type.iPhone4 }
else if nativeScaleFactor == 2.0 && nativeResolution == CGSize(width: 640, height: 1136) { return Type.iPhone5 }
else if nativeScaleFactor == 2.0 && nativeResolution == CGSize(width: 750, height: 1334) { return Type.iPhone6 }
else if (nativeScaleFactor-2.608) < 0.001 && nativeResolution == CGSize(width: 1080, height: 1920) { return Type.iPhone6Plus }
else if nativeScaleFactor == 3.0 && nativeResolution == CGSize(width: 1125, height: 2436) { return Type.iPhoneX }
else { return Type.unknowiPhone }
}
// iPad
else if interfaceIdiom == .pad {
if nativeScaleFactor == 2.0 && nativeResolution == CGSize(width: 1536, height: 2048) { return Type.iPad79 }
else if nativeScaleFactor == 2.0 && nativeResolution == CGSize(width: 2224, height: 1668) { return Type.iPad105 }
else if nativeScaleFactor == 2.0 && nativeResolution == CGSize(width: 2048, height: 2732) { return Type.iPad129 }
else { return Type.unknowiPad }
}
// Apple CarPlay
else if interfaceIdiom == .carPlay { return Type.carPlay }
// Apple TV
else if interfaceIdiom == .tv { return Type.tv }
// unknown device
else { return Type.unspecified }
}
}