Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import UIKit
- import SystemConfiguration.CaptiveNetwork
- import CoreTelephony.CTCarrier
- import CoreTelephony.CTTelephonyNetworkInfo
- public enum DeviceModel {
- case iPodTouch5
- case iPodTouch6
- case iPhone4
- case iPhone4s
- case iPhone5
- case iPhone5c
- case iPhone5s
- case iPhone6
- case iPhone6Plus
- case iPhone6s
- case iPhone6sPlus
- case iPhone7
- case iPhone7Plus
- case iPhoneSE
- case iPad2
- case iPad3
- case iPad4
- case iPadAir
- case iPadAir2
- case iPadMini
- case iPadMini2
- case iPadMini3
- case iPadMini4
- case iPadProSmall
- case iPadProLarge
- case appleTV
- case simulator
- case unknown
- }
- public struct Device {
- /// Gets the Device identifier String.
- public static var identifier: String {
- 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)))
- }
- return identifier
- }
- /// Gets the model name for the device.
- public static var model: DeviceModel {
- 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 "iPhone8,4": return .iPhoneSE
- case "iPhone9,1", "iPhone9,3": return .iPhone7
- case "iPhone9,2", "iPhone9,4": return .iPhone7Plus
- 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 .iPadProSmall
- case "iPad6,7", "iPad6,8": return .iPadProLarge
- case "AppleTV5,3": return .appleTV
- case "i386", "x86_64": return .simulator
- default: return .unknown
- }
- }
- /// hardware
- public struct CPU {
- /// physical core
- public static var core: Int {
- var size = 0
- sysctlbyname("hw.physicalcpu", nil, &size, nil, 0)
- var count:Int8 = 0
- sysctlbyname("hw.physicalcpu", &count, &size, nil, 0)
- return Int(count)
- }
- /// 线程 (4核8线程)
- public static var process: Int {
- return ProcessInfo.processInfo.activeProcessorCount
- }
- public struct Cache {
- /* 从 CPU 到 CPU 周期 大约需要的时间
- +----------+----------+--------------+
- | traget | cycle | time |
- +----------+-------------------------+
- | Memory | - | 60 - 80ns |
- +----------+-------------------------+
- | QPI | - | 20ns | /// QPI 总线传输(between sockets,not drawn)
- +----------+-------------------------+
- | L3 cache | 40-45 | 15ns |
- +----------+-------------------------+
- | L2 cache | 10 | 3ns |
- +----------+-------------------------+
- | L1 cache | 3-4 | 1ns |
- +----------+-------------------------+
- | 寄存器 | 1 | ---- |
- +----------+-------------------------+
- */
- /// bytes
- /// cpu 一级缓存
- public static var l1size: Int64 {
- var size = MemoryLayout.size(ofValue: Int.self)
- var count:Int64 = 0
- sysctlbyname("hw.l1icachesize", &count, &size, nil, 0)
- return count
- }
- /// bytes
- /// cpu 二级缓存
- /// - note: 是所有的核心的总和
- public static var l2size: Int64 {
- var size = MemoryLayout.size(ofValue: Int.self)
- var count:Int64 = 0
- sysctlbyname("hw.l2cachesize", &count, &size, nil, 0)
- return count
- }
- /// bytes
- /// cpu 三级缓存
- /// - note: 是所有的核心的总和
- public static var l3size: Int64 {
- var size = MemoryLayout.size(ofValue: Int.self)
- var count:Int64 = 0
- sysctlbyname("hw.l3cachesize", &count, &size, nil, 0)
- return count
- }
- /// bytes
- /// cpu 缓存行大小
- public static var linesize: Int { /// 4.72ms
- var size = MemoryLayout.size(ofValue: Int.self)
- var count:Int64 = 0
- sysctlbyname("hw.cachelinesize", &count, &size, nil, 0)
- return Int(count)
- }
- }
- public static var usage: Float? {
- let basicInfoCount = MemoryLayout<mach_task_basic_info_data_t>.size / MemoryLayout<natural_t>.size
- var kern: kern_return_t
- var threadList = UnsafeMutablePointer<thread_act_t>.allocate(capacity: 1)
- var threadCount = mach_msg_type_number_t(basicInfoCount)
- var threadInfo = thread_basic_info.init()
- var threadInfoCount: mach_msg_type_number_t
- var threadBasicInfo: thread_basic_info
- var threadStatistic: UInt32 = 0
- kern = withUnsafeMutablePointer(to: &threadList) {
- $0.withMemoryRebound(to: (thread_act_array_t?.self)!, capacity: 1) {
- task_threads(mach_task_self_, $0, &threadCount)
- }
- }
- if kern != KERN_SUCCESS {
- return nil
- }
- if threadCount > 0 {
- threadStatistic += threadCount
- }
- var totalUsageOfCPU: Float = 0.0
- for i in 0..<threadCount {
- threadInfoCount = mach_msg_type_number_t(THREAD_INFO_MAX)
- kern = withUnsafeMutablePointer(to: &threadInfo) {
- $0.withMemoryRebound(to: integer_t.self, capacity: 1) {
- thread_info(threadList[Int(i)], thread_flavor_t(THREAD_BASIC_INFO), $0, &threadInfoCount)
- }
- }
- if kern != KERN_SUCCESS {
- return nil
- }
- threadBasicInfo = threadInfo as thread_basic_info
- if threadBasicInfo.flags & TH_FLAGS_IDLE == 0 {
- totalUsageOfCPU = totalUsageOfCPU + Float(threadBasicInfo.cpu_usage) / Float(TH_USAGE_SCALE) * 100.0
- }
- }
- return totalUsageOfCPU
- }
- }
- }
- // MARK: - Memory
- extension Device {
- /// Memory
- public struct Memory {
- /// MB
- public static var capacity: Double? {
- /// to MB
- /// 方案一
- // var size = MemoryLayout.size(ofValue: Int.self)
- // var count:Int64 = 0
- // sysctlbyname("hw.memsize", &count, &size, nil, 0)
- // return Double(count / (1024 * 1024))
- /// 方案二
- return Double(ProcessInfo.processInfo.physicalMemory / (1024 * 1024))
- }
- /// virtual size of memory, in MB, nil for failure
- /// - Note: memory your process thinks it’s using
- public static var usage: Double? {
- guard let info = Device.Memory.taskBasicInfo else {
- return nil
- }
- return Double(info.virtual_size) / (1024 * 1024) /// to MB
- }
- /// resident size of memory, in MB, nil for failure
- /// - Note: physical memory used
- public static var resident: Double? {
- guard let info = Device.Memory.taskBasicInfo else {
- return nil
- }
- return Double(info.resident_size) / (1024 * 1024) /// to MB
- }
- public static var free: Double? {
- guard
- let capacity = Device.Memory.capacity,
- let usage = Device.Memory.usage else {
- return nil
- }
- return capacity - usage
- }
- private static var taskBasicInfo: mach_task_basic_info? {
- var info = mach_task_basic_info()
- var count = mach_msg_type_number_t(MemoryLayout.size(ofValue: info) / MemoryLayout<integer_t>.size)
- let kerr = withUnsafeMutablePointer(to: &info) { infoPtr in
- return infoPtr.withMemoryRebound(to: integer_t.self, capacity: Int(count)) { (machPtr: UnsafeMutablePointer<integer_t>) in
- return task_info(
- mach_task_self_,
- task_flavor_t(MACH_TASK_BASIC_INFO),
- machPtr,
- &count
- )
- }
- }
- guard kerr == KERN_SUCCESS else {
- return nil
- }
- return info
- }
- }
- }
- // MARK: - Disk
- extension Device {
- /// Disk
- public struct Disk {
- /// GB
- public static var capacity: Float? {
- guard let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).last else { return nil
- }
- let attributes = try? FileManager.default.attributesOfFileSystem(forPath: path as String)
- guard let value = (attributes?[.systemSize] as? NSNumber)?.int64Value else { return nil
- }
- return Float(value) / (1024 * 1024 * 1024) /// to GB
- }
- ///GB
- public static var free: Float? {
- guard let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).last else { return nil
- }
- let attributes = try? FileManager.default.attributesOfFileSystem(forPath: path as String)
- guard let value = (attributes?[.systemFreeSize] as? NSNumber)?.int64Value else { return nil
- }
- return Float(value) / (1024 * 1024 * 1024) /// to GB
- }
- }
- }
- // MARK: - Network
- extension Device {
- /// Network
- public struct Network {
- /// Connection
- // MARK: -
- public enum NetworkType {
- case wifi
- case wwan(String)
- }
- /// check network connection to apple.com
- public static var isAvailable: Bool {
- guard let flags = Device.Network.flags else {
- return false
- }
- /*
- target host is reachable and no connection is required
- the connection is on-demand (or on-traffic) if the calling application is using the CFSocketStream or higher APIs
- */
- return flags.contains(.reachable) ||
- !flags.contains(.connectionRequired) ||
- (flags.contains(.connectionOnDemand) || flags.contains(.connectionOnTraffic) && !flags.contains(.interventionRequired))
- }
- public static var type: NetworkType? {
- guard let flags = Device.Network.flags else {
- return nil
- }
- guard flags.contains(.reachable) else {
- return nil
- }
- #if os(iOS)
- if flags.contains(.isWWAN) {
- /// If the target host is reachable and carrier has no radio access technology, we assume you in wifi
- guard let accessTechnology = Device.Network.Carrier.currentRadioAccessTechnology else {
- return .wifi
- }
- return Device.Network.adpat(accessTechnology: accessTechnology)
- }
- #endif
- if !flags.contains(.connectionRequired) {
- return .wifi
- }
- if flags.contains(.connectionOnDemand) || flags.contains(.connectionOnTraffic) {
- if !flags.contains(.interventionRequired) {
- return .wifi
- }
- }
- return nil
- }
- private static var flags: SCNetworkReachabilityFlags? {
- var address = sockaddr_in()
- address.sin_len = UInt8(MemoryLayout<sockaddr_in>.size)
- address.sin_family = sa_family_t(AF_INET)
- guard let reachability = withUnsafePointer(to: &address, { pointer in
- return pointer.withMemoryRebound(to: sockaddr.self, capacity: MemoryLayout<sockaddr>.size) {
- return SCNetworkReachabilityCreateWithAddress(nil, $0)
- }
- }) else { return nil }
- var flags = SCNetworkReachabilityFlags()
- if SCNetworkReachabilityGetFlags(reachability, &flags) {
- return flags
- }
- return nil
- }
- /// 将 accessTechnology 变换成 2g 3g 4g
- private static func adpat(accessTechnology: String) -> NetworkType? {
- /// 4g
- if accessTechnology == CTRadioAccessTechnologyLTE {
- return .wwan("4G")
- }
- if Set([CTRadioAccessTechnologyWCDMA,
- CTRadioAccessTechnologyHSDPA,
- CTRadioAccessTechnologyCDMA1x,
- CTRadioAccessTechnologyCDMAEVDORev0,
- CTRadioAccessTechnologyCDMAEVDORevA,
- CTRadioAccessTechnologyCDMAEVDORevB,
- CTRadioAccessTechnologyeHRPD]).contains(accessTechnology) {
- return .wwan("3g")
- }
- if CTRadioAccessTechnologyGPRS == accessTechnology ||
- CTRadioAccessTechnologyEdge == accessTechnology {
- return .wwan("2g")
- }
- return nil
- }
- // MARK: -
- public struct Carrier {
- /// Carrier Name
- public static var name: String? {
- let carrier = Device.Network.Carrier.carrier
- guard let name = carrier?.carrierName, name.utf16.count != 0 else {
- return nil
- }
- return name
- }
- /// Carrier Country iso Code
- public static var isoCountryCode: String? {
- let carrier = Device.Network.Carrier.carrier
- guard let isoCountryCode = carrier?.isoCountryCode, isoCountryCode.utf16.count != 0 else {
- return nil
- }
- return isoCountryCode
- }
- /// current radio access technology
- public static var currentRadioAccessTechnology: String? {
- return CTTelephonyNetworkInfo().currentRadioAccessTechnology
- }
- /// is VOIP allowed
- public static var allowsVOIP: Bool {
- return Device.Network.Carrier.carrier?.allowsVOIP ?? false
- }
- private static var carrier: CTCarrier? {
- return CTTelephonyNetworkInfo().subscriberCellularProvider
- }
- }
- // MARK: -
- public struct WIFI {
- /// WIFI
- public static var ssid: String? {
- guard let interfaces = CNCopySupportedInterfaces() as? [CFString] else {
- return nil
- }
- for interface in interfaces {
- guard let info = CNCopyCurrentNetworkInfo(interface) as? [String:Any] else { continue }
- if let ssid = info[kCNNetworkInfoKeySSID as String] as? String {
- return ssid
- }
- }
- return nil
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement