From 762124d397aeaa4038034dbde201583d0358738d Mon Sep 17 00:00:00 2001 From: Dennis Weissmann Date: Sun, 15 Jan 2017 11:12:34 +0100 Subject: [PATCH] new swiftlint rules use swiftformat to format source code new (well, Swift 3) operator syntax (static funcs instead of global ones) bump version to 1.0.1 new implementation of `isZoomed` (which hopefully works now), this closes #59 --- .swiftlint.yml | 12 +- DeviceKit.h | 1 - DeviceKit.podspec | 2 +- DeviceKit.xcodeproj/project.pbxproj | 18 + Source/Device.swift | 718 ++++++++++++++-------------- Source/Info.plist | 2 +- Tests/Tests.swift | 46 +- 7 files changed, 410 insertions(+), 389 deletions(-) diff --git a/.swiftlint.yml b/.swiftlint.yml index b5c3e5b7..2c067257 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -1,11 +1,15 @@ opt_in_rules: - empty_count - - missing_docs + #- missing_docs - force_unwrapping + - overridden_super_call + - redundant_nil_coalescing + - redundant_optional_initialization + - redundant_void_return + - sorted_imports + - object_literal disabled_rules: - file_length + - line_length -line_length: - - 160 - - 160 diff --git a/DeviceKit.h b/DeviceKit.h index de1dd715..b97478a1 100644 --- a/DeviceKit.h +++ b/DeviceKit.h @@ -4,7 +4,6 @@ // // Created by Dennis Weissmann on 8/12/16. // -// @import Foundation; diff --git a/DeviceKit.podspec b/DeviceKit.podspec index 08906fec..8c1b4f31 100644 --- a/DeviceKit.podspec +++ b/DeviceKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'DeviceKit' - s.version = '1.0.0' + s.version = '1.0.1' s.summary = 'DeviceKit is a ยต-framework that provides a value-type replacement of UIDevice.' s.description = <<-DESC diff --git a/DeviceKit.xcodeproj/project.pbxproj b/DeviceKit.xcodeproj/project.pbxproj index c0a2ea1a..64355a08 100644 --- a/DeviceKit.xcodeproj/project.pbxproj +++ b/DeviceKit.xcodeproj/project.pbxproj @@ -119,6 +119,7 @@ isa = PBXNativeTarget; buildConfigurationList = 955EE5AB1D5E581B008C3DA8 /* Build configuration list for PBXNativeTarget "DeviceKit" */; buildPhases = ( + 958E8B081E2B7A70008C3B1B /* Code Formatting and Linting */, 955EE5951D5E581B008C3DA8 /* Sources */, 955EE5961D5E581B008C3DA8 /* Frameworks */, 955EE5971D5E581B008C3DA8 /* Headers */, @@ -205,6 +206,23 @@ }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + 958E8B081E2B7A70008C3B1B /* Code Formatting and Linting */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Code Formatting and Linting"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "command -v swiftformat >/dev/null 2>&1 || {\n echo >&2 \"swiftformat not found. Trying to install it via Homebrew...\"\n command -v brew >/dev/null 2>&1 || {\n echo >&2 \"Installing swiftformat via homebrew failed. Homebrew not found. Aborting.\"; exit 1;\n }\n echo >&2 \"Homebrew found, trying to install swiftformat.\";\n brew update && brew install swiftformat\n}\nswiftformat ${SRCROOT}/ --indent 2 --removelines disabled --disable trailingCommas\n\ncommand -v swiftlint >/dev/null 2>&1 || {\n echo >&2 \"swiftlint not found. Trying to install it via Homebrew...\"\n command -v brew >/dev/null 2>&1 || {\n echo >&2 \"Installing swiftlint via homebrew failed. Homebrew not found. Aborting.\"; exit 1;\n }\n echo >&2 \"Homebrew found, trying to install swiftlint.\";\n brew update && brew install swiftlint\n}\nswiftlint autocorrect\n\nswiftlint"; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ 955EE5951D5E581B008C3DA8 /* Sources */ = { isa = PBXSourcesBuildPhase; diff --git a/Source/Device.swift b/Source/Device.swift index 7501c97b..2bd658b7 100644 --- a/Source/Device.swift +++ b/Source/Device.swift @@ -6,12 +6,7 @@ // Copyright (c) 2014 Hot Action Studios. All rights reserved. // -import class UIKit.UIDevice -import class UIKit.UIScreen -import struct Darwin.utsname -import func Darwin.uname -import func Darwin.round -import func Darwin.getenv +import UIKit // MARK: - Device @@ -34,7 +29,7 @@ import func Darwin.getenv /// /// ... /// -/// if device.batteryState == .Full || device.batteryState >= .Charging(75) { +/// if device.batteryState == .full || device.batteryState >= .charging(75) { /// print("Your battery is happy! ๐Ÿ˜Š") /// } /// @@ -48,132 +43,132 @@ import func Darwin.getenv /// public enum Device { #if os(iOS) - /// Device is an [iPod Touch (5th generation)](https://support.apple.com/kb/SP657) - /// - /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP657/sp657_ipod-touch_size.jpg) - case iPodTouch5 - - /// Device is an [iPod Touch (6th generation)](https://support.apple.com/kb/SP720) - /// - /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP720/SP720-ipod-touch-specs-color-sg-2015.jpg) - case iPodTouch6 - - /// Device is an [iPhone 4](https://support.apple.com/kb/SP587) - /// - /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP643/sp643_iphone4s_color_black.jpg) - case iPhone4 - - /// Device is an [iPhone 4s](https://support.apple.com/kb/SP643) - /// - /// ![Image](https://support.apple.com/library/content/dam/edam/applecare/images/en_US/iphone/iphone5s/iphone_4s.png) - case iPhone4s - - /// Device is an [iPhone 5](https://support.apple.com/kb/SP655) - /// - /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP655/sp655_iphone5_color.jpg) - case iPhone5 - - /// Device is an [iPhone 5c](https://support.apple.com/kb/SP684) - /// - /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP684/SP684-color_yellow.jpg) - case iPhone5c - - /// Device is an [iPhone 5s](https://support.apple.com/kb/SP685) - /// - /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP685/SP685-color_black.jpg) - case iPhone5s - - /// Device is an [iPhone 6](https://support.apple.com/kb/SP705) - /// - /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP705/SP705-iphone_6-mul.png) - case iPhone6 - - /// Device is an [iPhone 6 Plus](https://support.apple.com/kb/SP706) - /// - /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP706/SP706-iphone_6_plus-mul.png) - case iPhone6Plus - - /// Device is an [iPhone 6s](https://support.apple.com/kb/SP726) - /// - /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP726/SP726-iphone6s-gray-select-2015.png) - case iPhone6s - - /// Device is an [iPhone 6s Plus](https://support.apple.com/kb/SP727) - /// - /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP727/SP727-iphone6s-plus-gray-select-2015.png) - case iPhone6sPlus - - /// Device is an [iPhone 7](https://support.apple.com/kb/SP) // TODO: Enter correct SP and image - /// - /// ![Image] - case iPhone7 - - /// Device is an [iPhone 7 Plus](https://support.apple.com/kb/SP) // TODO: Enter correct SP and image - /// - /// ![Image] - case iPhone7Plus - - /// Device is an [iPhone SE](https://support.apple.com/kb/SP738) - /// - /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP738/SP738.png) - case iPhoneSE - - /// Device is an [iPad 2](https://support.apple.com/kb/SP622) - /// - /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP622/SP622_01-ipad2-mul.png) - case iPad2 - - /// Device is an [iPad (3rd generation)](https://support.apple.com/kb/SP647) - /// - /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP662/sp662_ipad-4th-gen_color.jpg) - case iPad3 - - /// Device is an [iPad (4th generation)](https://support.apple.com/kb/SP662) - /// - /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP662/sp662_ipad-4th-gen_color.jpg) - case iPad4 - - /// Device is an [iPad Air](https://support.apple.com/kb/SP692) - /// - /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP692/SP692-specs_color-mul.png) - case iPadAir - - /// Device is an [iPad Air 2](https://support.apple.com/kb/SP708) - /// - /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP708/SP708-space_gray.jpeg) - case iPadAir2 - - /// Device is an [iPad Mini](https://support.apple.com/kb/SP661) - /// - /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP661/sp661_ipad_mini_color.jpg) - case iPadMini - - /// Device is an [iPad Mini 2](https://support.apple.com/kb/SP693) - /// - /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP693/SP693-specs_color-mul.png) - case iPadMini2 - - /// Device is an [iPad Mini 3](https://support.apple.com/kb/SP709) - /// - /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP709/SP709-space_gray.jpeg) - case iPadMini3 - - /// Device is an [iPad Mini 4](https://support.apple.com/kb/SP725) - /// - /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP725/SP725ipad-mini-4.png) - case iPadMini4 - - /// Device is an [iPad Pro](http://www.apple.com/ipad-pro/) - /// - /// ![Image](http://images.apple.com/v/ipad-pro/c/images/shared/buystrip/ipad_pro_large_2x.png) - case iPadPro9Inch - case iPadPro12Inch + /// Device is an [iPod Touch (5th generation)](https://support.apple.com/kb/SP657) + /// + /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP657/sp657_ipod-touch_size.jpg) + case iPodTouch5 + + /// Device is an [iPod Touch (6th generation)](https://support.apple.com/kb/SP720) + /// + /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP720/SP720-ipod-touch-specs-color-sg-2015.jpg) + case iPodTouch6 + + /// Device is an [iPhone 4](https://support.apple.com/kb/SP587) + /// + /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP643/sp643_iphone4s_color_black.jpg) + case iPhone4 + + /// Device is an [iPhone 4s](https://support.apple.com/kb/SP643) + /// + /// ![Image](https://support.apple.com/library/content/dam/edam/applecare/images/en_US/iphone/iphone5s/iphone_4s.png) + case iPhone4s + + /// Device is an [iPhone 5](https://support.apple.com/kb/SP655) + /// + /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP655/sp655_iphone5_color.jpg) + case iPhone5 + + /// Device is an [iPhone 5c](https://support.apple.com/kb/SP684) + /// + /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP684/SP684-color_yellow.jpg) + case iPhone5c + + /// Device is an [iPhone 5s](https://support.apple.com/kb/SP685) + /// + /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP685/SP685-color_black.jpg) + case iPhone5s + + /// Device is an [iPhone 6](https://support.apple.com/kb/SP705) + /// + /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP705/SP705-iphone_6-mul.png) + case iPhone6 + + /// Device is an [iPhone 6 Plus](https://support.apple.com/kb/SP706) + /// + /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP706/SP706-iphone_6_plus-mul.png) + case iPhone6Plus + + /// Device is an [iPhone 6s](https://support.apple.com/kb/SP726) + /// + /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP726/SP726-iphone6s-gray-select-2015.png) + case iPhone6s + + /// Device is an [iPhone 6s Plus](https://support.apple.com/kb/SP727) + /// + /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP727/SP727-iphone6s-plus-gray-select-2015.png) + case iPhone6sPlus + + /// Device is an [iPhone 7](https://support.apple.com/kb/SP743) + /// + /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP743/iphone7-black.png) + case iPhone7 + + /// Device is an [iPhone 7 Plus](https://support.apple.com/kb/SP744) + /// + /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP744/iphone7-plus-black.png) + case iPhone7Plus + + /// Device is an [iPhone SE](https://support.apple.com/kb/SP738) + /// + /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP738/SP738.png) + case iPhoneSE + + /// Device is an [iPad 2](https://support.apple.com/kb/SP622) + /// + /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP622/SP622_01-ipad2-mul.png) + case iPad2 + + /// Device is an [iPad (3rd generation)](https://support.apple.com/kb/SP647) + /// + /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP662/sp662_ipad-4th-gen_color.jpg) + case iPad3 + + /// Device is an [iPad (4th generation)](https://support.apple.com/kb/SP662) + /// + /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP662/sp662_ipad-4th-gen_color.jpg) + case iPad4 + + /// Device is an [iPad Air](https://support.apple.com/kb/SP692) + /// + /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP692/SP692-specs_color-mul.png) + case iPadAir + + /// Device is an [iPad Air 2](https://support.apple.com/kb/SP708) + /// + /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP708/SP708-space_gray.jpeg) + case iPadAir2 + + /// Device is an [iPad Mini](https://support.apple.com/kb/SP661) + /// + /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP661/sp661_ipad_mini_color.jpg) + case iPadMini + + /// Device is an [iPad Mini 2](https://support.apple.com/kb/SP693) + /// + /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP693/SP693-specs_color-mul.png) + case iPadMini2 + + /// Device is an [iPad Mini 3](https://support.apple.com/kb/SP709) + /// + /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP709/SP709-space_gray.jpeg) + case iPadMini3 + + /// Device is an [iPad Mini 4](https://support.apple.com/kb/SP725) + /// + /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP725/SP725ipad-mini-4.png) + case iPadMini4 + + /// Device is an [iPad Pro](http://www.apple.com/ipad-pro/) + /// + /// ![Image](http://images.apple.com/v/ipad-pro/c/images/shared/buystrip/ipad_pro_large_2x.png) + case iPadPro9Inch + case iPadPro12Inch #elseif os(tvOS) - /// Device is an [Apple TV](http://www.apple.com/tv/) - /// - /// ![Image](http://images.apple.com/v/tv/c/images/overview/buy_tv_large_2x.jpg) - case appleTV4 + /// Device is an [Apple TV](http://www.apple.com/tv/) + /// + /// ![Image](http://images.apple.com/v/tv/c/images/overview/buy_tv_large_2x.jpg) + case appleTV4 #endif /// Device is [Simulator](https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/iOS_Simulator_Guide/Introduction/Introduction.html) @@ -187,8 +182,6 @@ public enum Device { case unknown(String) /// Initializes a `Device` representing the current device this software runs on. - /// - /// - returns: An initialized `Device` public init() { self = Device.mapToDevice(identifier: Device.identifier) } @@ -211,181 +204,184 @@ public enum Device { /// - parameter identifier: The device identifier, e.g. "iPhone7,1". Can be obtained from `Device.identifier`. /// /// - returns: An initialized `Device`. - public static func mapToDevice(identifier: String) -> Device { // swiftlint:disable:this cyclomatic_complexity + public static func mapToDevice(identifier: String) -> Device { // swiftlint:disable:this cyclomatic_complexity #if os(iOS) switch identifier { - case "iPod5,1": return iPodTouch5 - case "iPod7,1": return iPodTouch6 - case "iPhone3,1", "iPhone3,2", "iPhone3,3": return iPhone4 - case "iPhone4,1": return iPhone4s - case "iPhone5,1", "iPhone5,2": return iPhone5 - case "iPhone5,3", "iPhone5,4": return iPhone5c - case "iPhone6,1", "iPhone6,2": return iPhone5s - case "iPhone7,2": return iPhone6 - case "iPhone7,1": return iPhone6Plus - case "iPhone8,1": return iPhone6s - case "iPhone8,2": return iPhone6sPlus - case "iPhone9,1", "iPhone9,3": return iPhone7 - case "iPhone9,2", "iPhone9,4": return iPhone7Plus - case "iPhone8,4": return iPhoneSE + case "iPod5,1": return iPodTouch5 + case "iPod7,1": return iPodTouch6 + case "iPhone3,1", "iPhone3,2", "iPhone3,3": return iPhone4 + case "iPhone4,1": return iPhone4s + case "iPhone5,1", "iPhone5,2": return iPhone5 + case "iPhone5,3", "iPhone5,4": return iPhone5c + case "iPhone6,1", "iPhone6,2": return iPhone5s + case "iPhone7,2": return iPhone6 + case "iPhone7,1": return iPhone6Plus + case "iPhone8,1": return iPhone6s + case "iPhone8,2": return iPhone6sPlus + case "iPhone9,1", "iPhone9,3": return iPhone7 + case "iPhone9,2", "iPhone9,4": return iPhone7Plus + case "iPhone8,4": return iPhoneSE case "iPad2,1", "iPad2,2", "iPad2,3", "iPad2,4":return iPad2 - case "iPad3,1", "iPad3,2", "iPad3,3": return iPad3 - case "iPad3,4", "iPad3,5", "iPad3,6": return iPad4 - case "iPad4,1", "iPad4,2", "iPad4,3": return iPadAir - case "iPad5,3", "iPad5,4": return iPadAir2 - case "iPad2,5", "iPad2,6", "iPad2,7": return iPadMini - case "iPad4,4", "iPad4,5", "iPad4,6": return iPadMini2 - case "iPad4,7", "iPad4,8", "iPad4,9": return iPadMini3 - case "iPad5,1", "iPad5,2": return iPadMini4 - case "iPad6,3", "iPad6,4": return iPadPro9Inch - case "iPad6,7", "iPad6,8": return iPadPro12Inch - case "i386", "x86_64": return simulator(mapToDevice( - identifier: ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] ?? "iOS" - )) - default: return unknown(identifier) + case "iPad3,1", "iPad3,2", "iPad3,3": return iPad3 + case "iPad3,4", "iPad3,5", "iPad3,6": return iPad4 + case "iPad4,1", "iPad4,2", "iPad4,3": return iPadAir + case "iPad5,3", "iPad5,4": return iPadAir2 + case "iPad2,5", "iPad2,6", "iPad2,7": return iPadMini + case "iPad4,4", "iPad4,5", "iPad4,6": return iPadMini2 + case "iPad4,7", "iPad4,8", "iPad4,9": return iPadMini3 + case "iPad5,1", "iPad5,2": return iPadMini4 + case "iPad6,3", "iPad6,4": return iPadPro9Inch + case "iPad6,7", "iPad6,8": return iPadPro12Inch + case "i386", "x86_64": return simulator(mapToDevice(identifier: ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] ?? "iOS")) + default: return unknown(identifier) } #elseif os(tvOS) switch identifier { - case "AppleTV5,3": return appleTV4 - case "i386", "x86_64": return simulator(mapToDevice( - identifier: ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] ?? "tvOS" - )) - default: return unknown(identifier) + case "AppleTV5,3": return appleTV4 + case "i386", "x86_64": return simulator(mapToDevice(identifier: ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] ?? "tvOS")) + default: return unknown(identifier) } #endif } #if os(iOS) - public static var allPods: [Device] { - return [.iPodTouch5, .iPodTouch6] - } - /// All iPhones - public static var allPhones: [Device] { - return [.iPhone4, iPhone4s, .iPhone5, .iPhone5s, .iPhone5c, .iPhone6, .iPhone6Plus, .iPhoneSE, .iPhone6s, .iPhone6sPlus, .iPhone7, .iPhone7Plus] - } + /// All iPods + public static var allPods: [Device] { + return [.iPodTouch5, .iPodTouch6] + } - /// All iPads - public static var allPads: [Device] { - return [.iPad2, .iPad3, .iPad4, .iPadAir, .iPadAir2, .iPadMini, .iPadMini2, .iPadMini3, .iPadMini4, .iPadPro9Inch, .iPadPro12Inch] - } + /// All iPhones + public static var allPhones: [Device] { + return [.iPhone4, iPhone4s, .iPhone5, .iPhone5s, .iPhone5c, .iPhone6, .iPhone6Plus, .iPhoneSE, .iPhone6s, .iPhone6sPlus, .iPhone7, .iPhone7Plus] + } - /// All simulator iPods - public static var allSimulatorPods: [Device] { - return allPods.map(Device.simulator) - } + /// All iPads + public static var allPads: [Device] { + return [.iPad2, .iPad3, .iPad4, .iPadAir, .iPadAir2, .iPadMini, .iPadMini2, .iPadMini3, .iPadMini4, .iPadPro9Inch, .iPadPro12Inch] + } - /// All simulator iPhones - public static var allSimulatorPhones: [Device] { - return allPhones.map(Device.simulator) - } + /// All simulator iPods + public static var allSimulatorPods: [Device] { + return allPods.map(Device.simulator) + } - /// All simulator iPads - public static var allSimulatorPads: [Device] { - return allPads.map(Device.simulator) - } + /// All simulator iPhones + public static var allSimulatorPhones: [Device] { + return allPhones.map(Device.simulator) + } - /// Returns whether the device is an iPod (real or simulator) - public var isPod: Bool { - return self.isOneOf(Device.allPods) || self.isOneOf(Device.allSimulatorPods) - } + /// All simulator iPads + public static var allSimulatorPads: [Device] { + return allPads.map(Device.simulator) + } - /// Returns whether the device is an iPhone (real or simulator) - public var isPhone: Bool { - return self.isOneOf(Device.allPhones) || self.isOneOf(Device.allSimulatorPhones) - } + /// Returns whether the device is an iPod (real or simulator) + public var isPod: Bool { + return self.isOneOf(Device.allPods) || self.isOneOf(Device.allSimulatorPods) + } - /// Returns whether the device is an iPad (real or simulator) - public var isPad: Bool { - return self.isOneOf(Device.allPads) || self.isOneOf(Device.allSimulatorPads) - } + /// Returns whether the device is an iPhone (real or simulator) + public var isPhone: Bool { + return self.isOneOf(Device.allPhones) || self.isOneOf(Device.allSimulatorPhones) + } - /// Returns whether the device is any of the simulator - /// Useful when there is a need to check and skip running a portion of code (location request or others) - public var isSimulator: Bool { - return self.isOneOf(Device.allSimulators) - } + /// Returns whether the device is an iPad (real or simulator) + public var isPad: Bool { + return self.isOneOf(Device.allPads) || self.isOneOf(Device.allSimulatorPads) + } - public var isZoomed: Bool { - return UIScreen.main.scale < UIScreen.main.nativeScale - } + /// Returns whether the device is any of the simulator + /// Useful when there is a need to check and skip running a portion of code (location request or others) + public var isSimulator: Bool { + return self.isOneOf(Device.allSimulators) + } - /// Returns diagonal screen length in inch as Float - public var diagonal: Float { - switch self { - case .iPodTouch5: return 4 - case .iPodTouch6: return 4 - case .iPhone4: return 3.5 - case .iPhone4s: return 3.5 - case .iPhone5: return 4 - case .iPhone5c: return 4 - case .iPhone5s: return 4 - case .iPhone6: return 4.7 - case .iPhone6Plus: return 5.5 - case .iPhone6s: return 4.7 - case .iPhone6sPlus: return 5.5 - case .iPhone7: return 4.7 - case .iPhone7Plus: return 5.5 - case .iPhoneSE: return 4 - case .iPad2: return 9.7 - case .iPad3: return 9.7 - case .iPad4: return 9.7 - case .iPadAir: return 9.7 - case .iPadAir2: return 9.7 - case .iPadMini: return 7.9 - case .iPadMini2: return 7.9 - case .iPadMini3: return 7.9 - case .iPadMini4: return 7.9 - case .iPadPro9Inch: return 9.7 - case .iPadPro12Inch: return 12.9 - case .simulator(let model): return model.diagonal - case .unknown(_): return -1 - } - } + public var isZoomed: Bool { + if Int(UIScreen.main.scale.rounded()) == 3 { + // Plus-sized + return UIScreen.main.nativeScale > 2.7 + } else { + return UIScreen.main.nativeScale > UIScreen.main.scale + } + } + + /// Returns diagonal screen length in inch as Float + public var diagonal: Float { + switch self { + case .iPodTouch5: return 4 + case .iPodTouch6: return 4 + case .iPhone4: return 3.5 + case .iPhone4s: return 3.5 + case .iPhone5: return 4 + case .iPhone5c: return 4 + case .iPhone5s: return 4 + case .iPhone6: return 4.7 + case .iPhone6Plus: return 5.5 + case .iPhone6s: return 4.7 + case .iPhone6sPlus: return 5.5 + case .iPhone7: return 4.7 + case .iPhone7Plus: return 5.5 + case .iPhoneSE: return 4 + case .iPad2: return 9.7 + case .iPad3: return 9.7 + case .iPad4: return 9.7 + case .iPadAir: return 9.7 + case .iPadAir2: return 9.7 + case .iPadMini: return 7.9 + case .iPadMini2: return 7.9 + case .iPadMini3: return 7.9 + case .iPadMini4: return 7.9 + case .iPadPro9Inch: return 9.7 + case .iPadPro12Inch: return 12.9 + case .simulator(let model): return model.diagonal + case .unknown: return -1 + } + } - /// Returns screen ratio as a tuple (width: Float, height: Float) + /// Returns screen ratio as a tuple (width: Float, height: Float) public var screenRatio: (width: Float, height: Float) { - switch self { - case .iPodTouch5: return (width: 9, height: 16) - case .iPodTouch6: return (width: 9, height: 16) - case .iPhone4: return (width: 2, height: 3) - case .iPhone4s: return (width: 2, height: 3) - case .iPhone5: return (width: 9, height: 16) - case .iPhone5c: return (width: 9, height: 16) - case .iPhone5s: return (width: 9, height: 16) - case .iPhone6: return (width: 9, height: 16) - case .iPhone6Plus: return (width: 9, height: 16) - case .iPhone6s: return (width: 9, height: 16) - case .iPhone6sPlus: return (width: 9, height: 16) - case .iPhone7: return (width: 9, height: 16) - case .iPhone7Plus: return (width: 9, height: 16) - case .iPhoneSE: return (width: 9, height: 16) - case .iPad2: return (width: 3, height: 4) - case .iPad3: return (width: 3, height: 4) - case .iPad4: return (width: 3, height: 4) - case .iPadAir: return (width: 3, height: 4) - case .iPadAir2: return (width: 3, height: 4) - case .iPadMini: return (width: 3, height: 4) - case .iPadMini2: return (width: 3, height: 4) - case .iPadMini3: return (width: 3, height: 4) - case .iPadMini4: return (width: 3, height: 4) - case .iPadPro9Inch: return (width: 3, height: 4) - case .iPadPro12Inch: return (width: 3, height: 4) - case .simulator(let model): return model.screenRatio - case .unknown(_): return (width: -1, height: -1) + switch self { + case .iPodTouch5: return (width: 9, height: 16) + case .iPodTouch6: return (width: 9, height: 16) + case .iPhone4: return (width: 2, height: 3) + case .iPhone4s: return (width: 2, height: 3) + case .iPhone5: return (width: 9, height: 16) + case .iPhone5c: return (width: 9, height: 16) + case .iPhone5s: return (width: 9, height: 16) + case .iPhone6: return (width: 9, height: 16) + case .iPhone6Plus: return (width: 9, height: 16) + case .iPhone6s: return (width: 9, height: 16) + case .iPhone6sPlus: return (width: 9, height: 16) + case .iPhone7: return (width: 9, height: 16) + case .iPhone7Plus: return (width: 9, height: 16) + case .iPhoneSE: return (width: 9, height: 16) + case .iPad2: return (width: 3, height: 4) + case .iPad3: return (width: 3, height: 4) + case .iPad4: return (width: 3, height: 4) + case .iPadAir: return (width: 3, height: 4) + case .iPadAir2: return (width: 3, height: 4) + case .iPadMini: return (width: 3, height: 4) + case .iPadMini2: return (width: 3, height: 4) + case .iPadMini3: return (width: 3, height: 4) + case .iPadMini4: return (width: 3, height: 4) + case .iPadPro9Inch: return (width: 3, height: 4) + case .iPadPro12Inch: return (width: 3, height: 4) + case .simulator(let model): return model.screenRatio + case .unknown: return (width: -1, height: -1) + } } - } - + #elseif os(tvOS) - /// All TVs - public static var allTVs: [Device] { - return [.appleTV4] - } + /// All TVs + public static var allTVs: [Device] { + return [.appleTV4] + } - /// All simulator TVs - public static var allSimulatorTVs: [Device] { - return allTVs.map(Device.simulator) - } + /// All simulator TVs + public static var allSimulatorTVs: [Device] { + return allTVs.map(Device.simulator) + } #endif /// All real devices (i.e. all devices except for all simulators) @@ -396,6 +392,7 @@ public enum Device { return allTVs #endif } + /// All simulators public static var allSimulators: [Device] { return allRealDevices.map(Device.simulator) @@ -452,11 +449,11 @@ public enum Device { private init() { switch UIDevice.current.userInterfaceIdiom { - case .pad: self = .pad - case .phone: self = .phone - case .tv: self = .tv - case .carPlay: self = .carPlay - default: self = .unspecified + case .pad: self = .pad + case .phone: self = .phone + case .tv: self = .tv + case .carPlay: self = .carPlay + default: self = .unspecified } } @@ -495,55 +492,57 @@ extension Device: CustomStringConvertible { public var description: String { #if os(iOS) switch self { - case .iPodTouch5: return "iPod Touch 5" - case .iPodTouch6: return "iPod Touch 6" - case .iPhone4: return "iPhone 4" - case .iPhone4s: return "iPhone 4s" - case .iPhone5: return "iPhone 5" - case .iPhone5c: return "iPhone 5c" - case .iPhone5s: return "iPhone 5s" - case .iPhone6: return "iPhone 6" - case .iPhone6Plus: return "iPhone 6 Plus" - case .iPhone6s: return "iPhone 6s" - case .iPhone6sPlus: return "iPhone 6s Plus" - case .iPhone7: return "iPhone 7" - case .iPhone7Plus: return "iPhone 7 Plus" - case .iPhoneSE: return "iPhone SE" - case .iPad2: return "iPad 2" - case .iPad3: return "iPad 3" - case .iPad4: return "iPad 4" - case .iPadAir: return "iPad Air" - case .iPadAir2: return "iPad Air 2" - case .iPadMini: return "iPad Mini" - case .iPadMini2: return "iPad Mini 2" - case .iPadMini3: return "iPad Mini 3" - case .iPadMini4: return "iPad Mini 4" - case .iPadPro9Inch: return "iPad Pro (9.7-inch)" - case .iPadPro12Inch: return "iPad Pro (12.9-inch)" - case .simulator(let model): return "Simulator (\(model))" - case .unknown(let identifier): return identifier + case .iPodTouch5: return "iPod Touch 5" + case .iPodTouch6: return "iPod Touch 6" + case .iPhone4: return "iPhone 4" + case .iPhone4s: return "iPhone 4s" + case .iPhone5: return "iPhone 5" + case .iPhone5c: return "iPhone 5c" + case .iPhone5s: return "iPhone 5s" + case .iPhone6: return "iPhone 6" + case .iPhone6Plus: return "iPhone 6 Plus" + case .iPhone6s: return "iPhone 6s" + case .iPhone6sPlus: return "iPhone 6s Plus" + case .iPhone7: return "iPhone 7" + case .iPhone7Plus: return "iPhone 7 Plus" + case .iPhoneSE: return "iPhone SE" + case .iPad2: return "iPad 2" + case .iPad3: return "iPad 3" + case .iPad4: return "iPad 4" + case .iPadAir: return "iPad Air" + case .iPadAir2: return "iPad Air 2" + case .iPadMini: return "iPad Mini" + case .iPadMini2: return "iPad Mini 2" + case .iPadMini3: return "iPad Mini 3" + case .iPadMini4: return "iPad Mini 4" + case .iPadPro9Inch: return "iPad Pro (9.7-inch)" + case .iPadPro12Inch: return "iPad Pro (12.9-inch)" + case .simulator(let model): return "Simulator (\(model))" + case .unknown(let identifier): return identifier } #elseif os(tvOS) switch self { - case .appleTV4: return "Apple TV 4" - case .simulator(let model): return "Simulator (\(model))" - case .unknown(let identifier): return identifier + case .appleTV4: return "Apple TV 4" + case .simulator(let model): return "Simulator (\(model))" + case .unknown(let identifier): return identifier } #endif } } // MARK: - Equatable -extension Device: Equatable {} +extension Device: Equatable { + + /// Compares two devices + /// + /// - parameter lhs: A device. + /// - parameter rhs: Another device. + /// + /// - returns: `true` iff the underlying identifier is the same. + public static func == (lhs: Device, rhs: Device) -> Bool { + return lhs.description == rhs.description + } -/// Compares two devices -/// -/// - parameter lhs: A device. -/// - parameter rhs: Another device. -/// -/// - returns: `true` iff the underlying identifier is the same. -public func == (lhs: Device, rhs: Device) -> Bool { - return lhs.description == rhs.description } #if os(iOS) @@ -568,13 +567,13 @@ public func == (lhs: Device, rhs: Device) -> Bool { fileprivate init() { UIDevice.current.isBatteryMonitoringEnabled = true - let batteryLevel = Int(round(UIDevice.current.batteryLevel * 100)) // round() is actually not needed anymore since -[batteryLevel] seems to always return a two-digit precision number + let batteryLevel = Int(round(UIDevice.current.batteryLevel * 100)) // round() is actually not needed anymore since -[batteryLevel] seems to always return a two-digit precision number // but maybe that changes in the future. switch UIDevice.current.batteryState { case .charging: self = .charging(batteryLevel) - case .full: self = .full + case .full: self = .full case .unplugged:self = .unplugged(batteryLevel) - case .unknown: self = .full // Should never happen since `batteryMonitoring` is enabled. + case .unknown: self = .full // Should never happen since `batteryMonitoring` is enabled. } UIDevice.current.isBatteryMonitoringEnabled = false } @@ -588,9 +587,9 @@ public func == (lhs: Device, rhs: Device) -> Bool { /// ``` public var description: String { switch self { - case .charging(let batteryLevel): return "Battery level: \(batteryLevel)%, device is plugged in." - case .full: return "Battery level: 100 % (Full), device is plugged in." - case .unplugged(let batteryLevel): return "Battery level: \(batteryLevel)%, device is unplugged." + case .charging(let batteryLevel): return "Battery level: \(batteryLevel)%, device is plugged in." + case .full: return "Battery level: 100 % (Full), device is plugged in." + case .unplugged(let batteryLevel): return "Battery level: \(batteryLevel)%, device is unplugged." } } @@ -604,8 +603,8 @@ public func == (lhs: Device, rhs: Device) -> Bool { /// Battery level ranges from 0 (fully discharged) to 100 (100% charged). public var batteryLevel: Int { switch BatteryState() { - case .charging(let value): return value - case .full: return 100 + case .charging(let value): return value + case .full: return 100 case .unplugged(let value): return value } } @@ -613,33 +612,34 @@ public func == (lhs: Device, rhs: Device) -> Bool { } // MARK: - Device.Batterystate: Comparable - extension Device.BatteryState: Comparable {} - - /// Tells if two battery states are equal. - /// - /// - parameter lhs: A battery state. - /// - parameter rhs: Another battery state. - /// - /// - returns: `true` iff they are equal, otherwise `false` - public func == (lhs: Device.BatteryState, rhs: Device.BatteryState) -> Bool { - return lhs.description == rhs.description - } + extension Device.BatteryState: Comparable { + /// Tells if two battery states are equal. + /// + /// - parameter lhs: A battery state. + /// - parameter rhs: Another battery state. + /// + /// - returns: `true` iff they are equal, otherwise `false` + public static func == (lhs: Device.BatteryState, rhs: Device.BatteryState) -> Bool { + return lhs.description == rhs.description + } - /// Compares two battery states. - /// - /// - parameter lhs: A battery state. - /// - parameter rhs: Another battery state. - /// - /// - returns: `true` if rhs is `.Full`, `false` when lhs is `.Full` otherwise their battery level is compared. - public func < (lhs: Device.BatteryState, rhs: Device.BatteryState) -> Bool { - switch (lhs, rhs) { - case (.full, _): return false // return false (even if both are `.Full` -> they are equal) - case (_, .full): return true // lhs is *not* `.Full`, rhs is - case (.charging(let lhsLevel), .charging(let rhsLevel)): return lhsLevel < rhsLevel - case (.charging(let lhsLevel), .unplugged(let rhsLevel)): return lhsLevel < rhsLevel - case (.unplugged(let lhsLevel), .charging(let rhsLevel)): return lhsLevel < rhsLevel - case (.unplugged(let lhsLevel), .unplugged(let rhsLevel)): return lhsLevel < rhsLevel - default: return false // compiler won't compile without it, though it cannot happen + /// Compares two battery states. + /// + /// - parameter lhs: A battery state. + /// - parameter rhs: Another battery state. + /// + /// - returns: `true` if rhs is `.Full`, `false` when lhs is `.Full` otherwise their battery level is compared. + public static func < (lhs: Device.BatteryState, rhs: Device.BatteryState) -> Bool { + switch (lhs, rhs) { + case (.full, _): return false // return false (even if both are `.Full` -> they are equal) + case (_, .full): return true // lhs is *not* `.Full`, rhs is + case (.charging(let lhsLevel), .charging(let rhsLevel)): return lhsLevel < rhsLevel + case (.charging(let lhsLevel), .unplugged(let rhsLevel)): return lhsLevel < rhsLevel + case (.unplugged(let lhsLevel), .charging(let rhsLevel)): return lhsLevel < rhsLevel + case (.unplugged(let lhsLevel), .unplugged(let rhsLevel)): return lhsLevel < rhsLevel + default: return false // compiler won't compile without it, though it cannot happen + } } } + #endif diff --git a/Source/Info.plist b/Source/Info.plist index 60b9c008..7a845533 100644 --- a/Source/Info.plist +++ b/Source/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.0.0 + 1.0.1 CFBundleSignature ???? CFBundleVersion diff --git a/Tests/Tests.swift b/Tests/Tests.swift index 5a9c30e2..3318b429 100644 --- a/Tests/Tests.swift +++ b/Tests/Tests.swift @@ -6,8 +6,8 @@ // Copyright (c) 2015 Hot Action Studios. All rights reserved. // -import XCTest @testable import DeviceKit +import XCTest class DeviceKitTests: XCTestCase { @@ -21,37 +21,37 @@ class DeviceKitTests: XCTestCase { // MARK: - iOS #if os(iOS) - func testIsSimulator() { - XCTAssert(Device().isSimulator) - } + func testIsSimulator() { + XCTAssert(Device().isSimulator) + } - func testOperator1() { - XCTAssert(Device.BatteryState.full > Device.BatteryState.charging(100)) - } + func testOperator1() { + XCTAssert(Device.BatteryState.full > Device.BatteryState.charging(100)) + } - func testOperator2() { - XCTAssert(Device.BatteryState.charging(75) != Device.BatteryState.unplugged(75)) - } + func testOperator2() { + XCTAssert(Device.BatteryState.charging(75) != Device.BatteryState.unplugged(75)) + } - func testOperator3() { - XCTAssert(Device.BatteryState.unplugged(2) > Device.BatteryState.charging(1)) - } + func testOperator3() { + XCTAssert(Device.BatteryState.unplugged(2) > Device.BatteryState.charging(1)) + } - func testDescriptionFromIdentifier() { - XCTAssert(Device.mapToDevice(identifier: "iPhone3,1").description == "iPhone 4") - } + func testDescriptionFromIdentifier() { + XCTAssert(Device.mapToDevice(identifier: "iPhone3,1").description == "iPhone 4") + } #endif // MARK: - tvOS #if os(tvOS) - func testIsSimulator() { - XCTAssert(Device().isOneOf(Device.allSimulatorTVs)) - } + func testIsSimulator() { + XCTAssert(Device().isOneOf(Device.allSimulatorTVs)) + } - func testDescriptionFromIdentifier() { - XCTAssert(Device.mapToDevice(identifier: "AppleTV5,3").description == "Apple TV 4") - } + func testDescriptionFromIdentifier() { + XCTAssert(Device.mapToDevice(identifier: "AppleTV5,3").description == "Apple TV 4") + } #endif - + }