iOS_手機(jī)信息收集

  • 軟件: Xcode9.1
  • 語(yǔ)言: Swift4
  • 真機(jī)調(diào)試系統(tǒng): iOS10.3

目錄

    |_ 1. app版本號(hào)
    |_ 2. 系統(tǒng)名稱
    |_ 3. 當(dāng)前系統(tǒng)版本號(hào)
    |_ 4. 設(shè)備的唯一標(biāo)識(shí)
    |_ 5. model
    |_ 6. 設(shè)備型號(hào)
    |_ 7. 手機(jī)磁盤(pán)空間(手機(jī)總空間,手機(jī)剩余空間)
    |_ 8.系統(tǒng)時(shí)間
        |_ 8.1 系統(tǒng)運(yùn)行時(shí)間
        |_ 8.2 系統(tǒng)啟動(dòng)時(shí)間
    |_ 9. 電池
        |_ 9.1 當(dāng)前電池電量
        |_ 9.2 電池當(dāng)前的狀態(tài)
    |_ 10. 運(yùn)營(yíng)商
    |_ 11. 內(nèi)存
        |_ 11.1 手機(jī)物理內(nèi)存
        |_ 11.2 內(nèi)存使用情況 (free、active虫啥、inactive、wired、compressed)
        |_ 11.3 當(dāng)前任務(wù)所占用的內(nèi)存
    |_ 12. 手機(jī)網(wǎng)絡(luò)IP地址
        |_ 12.1 移動(dòng)網(wǎng)絡(luò)IP地址
        |_ 12.2 僅wifi網(wǎng)絡(luò)IP地址
        |_ 12.3 公網(wǎng)IP地址
    |_ 13.CPU使用率(system, user, idle, nice)
    |_ 14.網(wǎng)絡(luò)狀態(tài)
        |_ 14.1 網(wǎng)絡(luò)是否連接
        |_ 14.2 網(wǎng)絡(luò)連接類型(2G车摄、3G剂公、4G惫恼、WIFI)
1. app版本號(hào)
    /// app版本號(hào)
    ///
    /// - Returns: app版本號(hào)
    open static func appVerion() -> String {
        return Bundle.main.infoDictionary!["CFBundleShortVersionString"] as! String
    }
2. 系統(tǒng)名稱
    /// 系統(tǒng)名稱理澎,如iPhone OS
    ///
    /// - Returns: 當(dāng)前系統(tǒng)名稱
    open static func systemName() -> String {
        return UIDevice.current.systemName
    }
3. 當(dāng)前系統(tǒng)版本號(hào)
    /// 當(dāng)前系統(tǒng)版本號(hào)
    ///
    /// - Returns: 當(dāng)前系統(tǒng)版本號(hào)
    open static func systemVersion() -> String {
        return UIDevice.current.systemVersion
    }
4. 設(shè)備的唯一標(biāo)識(shí)
    /// 設(shè)備的唯一標(biāo)識(shí)號(hào),deviceID
    ///
    /// - Returns: 唯一識(shí)別碼uuid
    open static func uuid() -> String {
        return UIDevice.current.identifierForVendor!.uuidString
    }
5. model
    /// The model of the device煌往,如iPhone或者iPod touch
    ///
    /// - Returns: 設(shè)備
    open static func model() -> String {
        return UIDevice.current.model
    }
    
    /// The model of the device as a localized string倾哺,類似model
    ///
    /// - Returns: localizedModel
    open static func localizedModel() -> String {
        return UIDevice.current.localizedModel
    }
6. 設(shè)備型號(hào)
   /// 設(shè)備型號(hào)(iPod、iPhone刽脖、iPad)
    /// 詳細(xì)參考地址:https://www.theiphonewiki.com/wiki/Models
    /// - Returns: 設(shè)備型號(hào)
    open static func deviceName() -> 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)))
        }
        
        switch identifier {
        case "iPod4,1":                                 return "iPod Touch 4"
        case "iPod5,1":                                 return "iPod Touch 5"
        case "iPod7,1":                                 return "iPod Touch 6"
        case "iPhone3,1", "iPhone3,2", "iPhone3,3":     return "iPhone 4"
        case "iPhone4,1":                               return "iPhone 4s"
        case "iPhone5,1", "iPhone5,2":                  return "iPhone 5"
        case "iPhone5,3", "iPhone5,4":                  return "iPhone 5c"
        case "iPhone6,1", "iPhone6,2":                  return "iPhone 5s"
        case "iPhone7,2":                               return "iPhone 6"
        case "iPhone7,1":                               return "iPhone 6 Plus"
        case "iPhone8,1":                               return "iPhone 6s"
        case "iPhone8,2":                               return "iPhone 6s Plus"
        case "iPhone8,4":                               return "iPhone SE"
        case "iPhone9,1", "iPhone9,3":                  return "iPhone 7"
        case "iPhone9,2", "iPhone9,4":                  return "iPhone 7 Plus"
        case "iPhone10,1", "iPhone10,4":                return "iPhone 8"
        case "iPhone10,2", "iPhone10,5":                return "iPhone 8 Plus"
        case "iPhone10,3", "iPhone10,6":                return "iPhone X"
        case "iPad2,1", "iPad2,2", "iPad2,3", "iPad2,4":return "iPad 2"
        case "iPad3,1", "iPad3,2", "iPad3,3":           return "iPad 3"
        case "iPad3,4", "iPad3,5", "iPad3,6":           return "iPad 4"
        case "iPad4,1", "iPad4,2", "iPad4,3":           return "iPad Air"
        case "iPad5,3", "iPad5,4":                      return "iPad Air 2"
        case "iPad6,11", "iPad6,12":                    return "iPad 5"
        case "iPad2,5", "iPad2,6", "iPad2,7":           return "iPad Mini"
        case "iPad4,4", "iPad4,5", "iPad4,6":           return "iPad Mini 2"
        case "iPad4,7", "iPad4,8", "iPad4,9":           return "iPad Mini 3"
        case "iPad5,1", "iPad5,2":                      return "iPad Mini 4"
        case "iPad6,3", "iPad6,4":                      return "iPad Pro 9.7 Inch"
        case "iPad6,7", "iPad6,8":                      return "iPad Pro 12.9 Inch"
        case "iPad7,1", "iPad7,2":                      return "iPad Pro 12.9 Inch 2. Generation"
        case "iPad7,3", "iPad7,4":                      return "iPad Pro 10.5 Inch"
        case "i386", "x86_64":                          return "Simulator"
        default:                                        return identifier
        }
    }
7. 手機(jī)磁盤(pán)空間(手機(jī)總空間,手機(jī)剩余空間)
    /// 手機(jī)磁盤(pán)空間
    ///  - 手機(jī)總空間:手機(jī)上顯示的非真正的大小羞海。鏈接mac的iTunes可查看實(shí)際大小
    ///  - 手機(jī)剩余空間:因?yàn)楂@取到設(shè)備上剩余的可用空間與顯示的有差異,所以(+ - 200 Mb差異)
    ///  - 相關(guān)鏈接Q1:https://stackoverflow.com/questions/5712527/how-to-detect-total-available-free-disk-space-on-the-iphone-ipad-device
    ///  - 相關(guān)鏈接Q2:https://stackoverflow.com/questions/9270027/iphone-free-space-left-on-device-reported-incorrectly-200-mb-difference
    /// - Returns: (手機(jī)總空間,手機(jī)剩余空間)
    open static func getFreeDiskspace() -> (Double,Double) {
        var totalSpace:Double = 0.0
        var totalFreeSpace:Double = 0.0
        let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
        let dictionary = try? FileManager.default.attributesOfFileSystem(forPath: paths.last!)
        
        guard dictionary != nil else {
            return (totalSpace,totalFreeSpace)
        }
        
        let fileSystemSizeInBytes = dictionary![FileAttributeKey.systemSize] as! Double
        let freeFileSystemSizeInBytes = dictionary![FileAttributeKey.systemFreeSize] as! Double
        totalSpace = fileSystemSizeInBytes / pow(1024, 3)
        totalFreeSpace = (freeFileSystemSizeInBytes - (200 * pow(1024, 2))) / pow(1000, 3)
        return (totalSpace,totalFreeSpace)
    }
8.系統(tǒng)時(shí)間
8.1 系統(tǒng)運(yùn)行時(shí)間
    /// 系統(tǒng)運(yùn)行時(shí)間(運(yùn)行多少秒)
    ///
    /// - Returns: TimeInterval
    open static func getSystemUptime() -> TimeInterval {
        return ProcessInfo().systemUptime
    }
8.2 系統(tǒng)啟動(dòng)時(shí)間
    /// 系統(tǒng)啟動(dòng)時(shí)間
    ///
    /// - Returns: TimeInterval
    open static func getLaunchTime() -> TimeInterval {
        let nowTime = Date()
        let nowTimeInterval = nowTime.timeIntervalSince1970
        return nowTimeInterval - getSystemUptime()
    }
9. 電池
9.1 當(dāng)前電池電量
    /// 獲取當(dāng)前電池電量0.0~1.0
    ///
    /// - Returns: Float
    open static func getBatteryLevel() -> Float {
        UIDevice.current.isBatteryMonitoringEnabled = true
        return UIDevice.current.batteryLevel
    }
9.2 電池當(dāng)前的狀態(tài)
    /// 獲取電池當(dāng)前的狀態(tài),共有4種狀態(tài)
    ///  - .charging (plugged in, less than 100% - 充電中)
    ///  - .full (plugged in, at 100% - 滿電)
    ///  - .unplugged (on battery, discharging - 未充電,放電中)
    ///  - .unknown (isBatteryMonitoringEnabled is false)
    /// - Returns: UIDeviceBatteryState
    open static func getBatteryState() -> UIDeviceBatteryState {
        UIDevice.current.isBatteryMonitoringEnabled = true
        return UIDevice.current.batteryState
    }
10. 運(yùn)營(yíng)商
- import CoreTelephony

    /// 運(yùn)營(yíng)商
    /// - example: "中國(guó)移動(dòng)"
    /// - Returns: String
    open static func getCarrierName() -> String {
        let info = CTTelephonyNetworkInfo()
        let carrier = info.subscriberCellularProvider
        guard carrier != nil else {
            return ""
        }
        return carrier!.carrierName ?? ""
    }
11. 內(nèi)存
11.1 手機(jī)物理內(nèi)容
    /// 獲取總內(nèi)存大星堋(單位:GB)
    ///
    /// - Returns: Double
    open static func getTotalMemorySize() -> Double {
        return Double(ProcessInfo().physicalMemory) / pow(1024, 3)
    }
11.2 內(nèi)存使用情況 (free却邓、active、inactive院水、wired腊徙、compressed)
    /// 獲取當(dāng)前設(shè)備內(nèi)存使用情況(單位:GB)
    /// 參考: https://github.com/beltex/SystemKit
    /// - Returns: (free, active, inactive, wired, compressed)
    open static func memoryUsage() -> (free:Double, active:Double, inactive:Double, wired:Double, compressed:Double) {
        let stats = VMStatistics64()
        let PAGE_SIZE = vm_kernel_page_size
        let free = Double(stats.free_count) * Double(PAGE_SIZE) / pow(1024, 3)
        let active = Double(stats.active_count) * Double(PAGE_SIZE) / pow(1024, 3)
        let inactive = Double(stats.inactive_count) * Double(PAGE_SIZE) / pow(1024, 3)
        let wired = Double(stats.wire_count) * Double(PAGE_SIZE) / pow(1024, 3)
        
        // Result of the compression. This is what you see in Activity Monitor
        let compressed = Double(stats.compressor_page_count) * Double(PAGE_SIZE) / pow(1024, 3)
        
        return (free, active, inactive, wired, compressed)
    }

    /// 虛擬內(nèi)存統(tǒng)計(jì)信息
    ///
    /// - Returns: vm_statistics64
    fileprivate static func VMStatistics64() -> vm_statistics64 {
        let HOST_VM_INFO64_COUNT:mach_msg_type_number_t =
            UInt32(MemoryLayout<vm_statistics64_data_t>.size / MemoryLayout<integer_t>.size)
        var size = HOST_VM_INFO64_COUNT
        let hostInfo = vm_statistics64_t.allocate(capacity: 1)
        
        let result = hostInfo.withMemoryRebound(to: integer_t.self, capacity: Int(size)) {
            host_statistics64(mach_host_self(),
                              HOST_VM_INFO64,
                              $0,
                              &size)
        }
        
        let data = hostInfo.move()
        hostInfo.deallocate(capacity: 1)
        
        #if DEBUG
            if result != KERN_SUCCESS {
                print("ERROR - \(#file):\(#function) - kern_result_t = "
                    + "\(result)")
            }
        #endif
        
        return data
    }
11.3 當(dāng)前任務(wù)所占用的內(nèi)存
    /// 獲取當(dāng)前任務(wù)所占用的內(nèi)存(單位:GB)
    /// 參考: https://stackoverflow.com/questions/40991912/how-to-get-memory-usage-of-my-application-and-system-in-swift-by-programatically
    /// - Returns: Double
    open static func appUsedMemory() -> Double {
        var taskInfo = mach_task_basic_info()
        var count = mach_msg_type_number_t(MemoryLayout<mach_task_basic_info>.size)/4
        let kerr: kern_return_t = withUnsafeMutablePointer(to: &taskInfo) {
            $0.withMemoryRebound(to: integer_t.self, capacity: 1) {
                task_info(mach_task_self_, task_flavor_t(MACH_TASK_BASIC_INFO), $0, &count)
            }
        }
        #if DEBUG
            if kerr != KERN_SUCCESS {
                print("Error with task_info(): " +
                    (String(cString: mach_error_string(kerr), encoding: String.Encoding.ascii) ?? "unknown error"))
            }
        #endif
        return Double(taskInfo.resident_size) / pow(1024, 3)
    }
  • 以 MB 或 GB 字符串方式顯示:
    /// 以 MB 或 GB 字符串方式顯示
    ///
    /// - Parameter value: Double
    /// - Returns: String
    open static func memoryUnit(_ value: Double) -> String {
        if value < 1.0 {
            return String(format:"%.2f",value * 1000.0) + "MB"
        } else {
            return String(format:"%.2f", value) + "GB"
        }
    }
12. 手機(jī)網(wǎng)絡(luò)IP地址
fileprivate let IOS_CELLULAR = "pdp_ip0"
fileprivate let IOS_WIFI = "en0"
fileprivate let IOS_VPN = "utun0"
fileprivate let IP_ADDR_IPv4 = "ipv4"
fileprivate let IP_ADDR_IPv6 = "ipv6"
12.1 移動(dòng)網(wǎng)絡(luò)IP地址
    /// 獲取當(dāng)前手機(jī)網(wǎng)絡(luò)ip地址
    /// - example:
    ///         [ "awdl0/ipv6": "fe80::d0fa:xxxx:xxxx:xxxx%awdl0",
    ///           "en0/ipv6": "fe80::c95:xxxx:xxxx:xxxx%en0",
    ///           "pdp_ip0/ipv4": "10.199.xxx.xxx", // 移動(dòng)網(wǎng)絡(luò)ip地址
    ///           "en0/ipv4": "172.20.xxx.xxx", // Wi-Fi ip地址
    ///           "utun0/ipv6": "fe80::6b12:xxxx:xxxx:xxxx%utun0"]
    /// - Returns: [String:String]
    open static func getIFAddresses() -> [String:String] {
        var addresses = [String:String]()
        
        // Get list of all interfaces on the local machine:
        var ifaddr : UnsafeMutablePointer<ifaddrs>?
        guard getifaddrs(&ifaddr) == 0 else { return [:] }
        guard let firstAddr = ifaddr else { return [:] }
        
        // For each interface ...
        for ptr in sequence(first: firstAddr, next: { $0.pointee.ifa_next }) {
            let flags = Int32(ptr.pointee.ifa_flags)
            var addr = ptr.pointee.ifa_addr.pointee
            
            // Convert sockaddr to sockaddr_in
            var addr_in:sockaddr_in = withUnsafePointer(to: &addr, {
                $0.withMemoryRebound(to: sockaddr_in.self, capacity: 1) {
                    $0.pointee
                }
            })
            
            // Create UnsafeMutablePointer<CChar>
            let addrBuf = UnsafeMutablePointer<CChar>.allocate(capacity: Int(max(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)))
            // Check for running IPv4, IPv6 interfaces. Skip the loopback interface.
            if (flags & (IFF_UP|IFF_RUNNING|IFF_LOOPBACK)) == (IFF_UP|IFF_RUNNING) {
                if addr.sa_family == UInt8(AF_INET) || addr.sa_family == UInt8(AF_INET6) {
                    
                    // Convert interface address to a human readable string:
                    var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
                    if (getnameinfo(ptr.pointee.ifa_addr, socklen_t(addr.sa_len), &hostname, socklen_t(hostname.count),
                                    nil, socklen_t(0), NI_NUMERICHOST) == 0) {
                        let address = String(cString: hostname)
                        let name = String(cString: ptr.pointee.ifa_name)
                        var type = ""
                        
                        if addr_in.sin_family == UInt8(AF_INET) {
                            if (inet_ntop(AF_INET, &addr_in.sin_addr, addrBuf, socklen_t(INET_ADDRSTRLEN)) != nil) {
                                type = IP_ADDR_IPv4
                            }
                        }else {
                            // Convert sockaddr to sockaddr_in6
                            var addr6:sockaddr_in6 = withUnsafePointer(to: &addr, {
                                $0.withMemoryRebound(to: sockaddr_in6.self, capacity: 1) {
                                    $0.pointee
                                }
                            })
                            
                            if (inet_ntop(AF_INET, &addr6.sin6_addr, addrBuf, socklen_t(INET6_ADDRSTRLEN)) != nil) {
                                type = IP_ADDR_IPv6
                            }
                        }
                        
                        if !type.isEmpty {
                            let key = "\(name)/\(type)"
                            addresses[key] = address
                        }
                    }
                }
            }
        }
        
        freeifaddrs(ifaddr)
        return addresses
    }
12.2 僅wifi網(wǎng)絡(luò)IP地址
    /// 獲取當(dāng)前wifi的IP地址
    ///
    /// - Returns: String
    open static func getLocalIPAddressForCurrentWiFi() -> String? {
        var address: String?
        
        // get list of all interfaces on the local machine
        var ifaddr: UnsafeMutablePointer<ifaddrs>? = nil
        guard getifaddrs(&ifaddr) == 0 else {
            return nil
        }
        guard let firstAddr = ifaddr else {
            return nil
        }
        for ifptr in sequence(first: firstAddr, next: { $0.pointee.ifa_next }) {
            
            let interface = ifptr.pointee
            
            // Check for IPV4 or IPV6 interface
            let addrFamily = interface.ifa_addr.pointee.sa_family
            if addrFamily == UInt8(AF_INET) || addrFamily == UInt8(AF_INET6) {
                // Check interface name
                let name = String(cString: interface.ifa_name)
                if name == IOS_WIFI {
                    
                    // Convert interface address to a human readable string
                    var addr = interface.ifa_addr.pointee
                    var hostName = [CChar](repeating: 0, count: Int(NI_MAXHOST))
                    getnameinfo(&addr, socklen_t(interface.ifa_addr.pointee.sa_len), &hostName, socklen_t(hostName.count), nil, socklen_t(0), NI_NUMERICHOST)
                    address = String(cString: hostName)
                }
            }
        }
        
        freeifaddrs(ifaddr)
        return address
    }
12.3 公網(wǎng)IP地址
    /// 獲取公網(wǎng)ip
    ///可以通過(guò)接口請(qǐng)求查詢ip所在的省份, 格式:http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=json&ip=192.108.xxx.xxx
    /// http://ysj5125094.iteye.com/blog/2227874
    /// - Parameter url: input: www.baidu.com
    /// - Returns: String?
    open static func getIPAddressFromDNSQuery(url: String) -> String? {
        let host = CFHostCreateWithName(nil, url as CFString).takeRetainedValue()
        CFHostStartInfoResolution(host, .addresses, nil)
        var success: DarwinBoolean =  false
        if let address = CFHostGetAddressing(host, &success)?.takeUnretainedValue() as NSArray?, let theAddress = address.firstObject as? NSData {
            var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
            if getnameinfo(theAddress.bytes.assumingMemoryBound(to: sockaddr.self), socklen_t(theAddress.length), &hostname, socklen_t(hostname.count), nil, 0, NI_NUMERICHOST) == 0 {
                let numAddress = String(cString: hostname)
                return numAddress
            }
            return nil
        }
        return nil
    }
13.CPU使用率(system, user, idle, nice)
- fileprivate var loadPrevious = host_cpu_load_info()

    /// 獲取CPU使用率 (單位: 100%)
    /// 參考: https://github.com/beltex/SystemKit
    /// - Returns: (system, user, idle, nice)
    open static func usageCPU() -> (system:Double, user:Double, idle:Double, nice:Double) {
        
        let load = hostCPULoadInfo()
        
        let userDiff = Double(load.cpu_ticks.0 - loadPrevious.cpu_ticks.0)
        let sysDiff  = Double(load.cpu_ticks.1 - loadPrevious.cpu_ticks.1)
        let idleDiff = Double(load.cpu_ticks.2 - loadPrevious.cpu_ticks.2)
        let niceDiff = Double(load.cpu_ticks.3 - loadPrevious.cpu_ticks.3)
        let totalTicks = sysDiff + userDiff + niceDiff + idleDiff
        
        let sys  = sysDiff  / totalTicks * 100.0
        let user = userDiff / totalTicks * 100.0
        let idle = idleDiff / totalTicks * 100.0
        let nice = niceDiff / totalTicks * 100.0
        
        // the current and last call. Thus, first call will always be inaccurate.
        loadPrevious = load
        
        return (sys, user, idle, nice)
    }
    
    /// CPU負(fù)載信息
    ///
    /// - Returns: host_cpu_load_info
    fileprivate static func hostCPULoadInfo() -> host_cpu_load_info {
        var size:mach_msg_type_number_t =
            UInt32(MemoryLayout<host_cpu_load_info_data_t>.size / MemoryLayout<integer_t>.size)
        let hostInfo = host_cpu_load_info_t.allocate(capacity: 1)
        
        let result = hostInfo.withMemoryRebound(to: integer_t.self, capacity: Int(size)) {
            host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO,
                            $0,
                            &size)
        }
        
        let data = hostInfo.move()
        hostInfo.deallocate(capacity: 1)
        
        #if DEBUG
            if result != KERN_SUCCESS {
                print("ERROR - \(#file):\(#function) - kern_result_t = "
                    + "\(result)")
            }
        #endif
        
        return data
    }
14.網(wǎng)絡(luò)狀態(tài)
import SystemConfiguration
import CoreTelephony

/// Defines the various states of network reachability.
///
/// - unknown:      It is unknown whether the network is reachable.
/// - notReachable: The network is not reachable.
/// - reachable:    The network is reachable.
public enum NetworkReachabilityStatus {
    case unknown
    case notReachable
    case reachable(ConnectionType)
}

/// Defines the various connection types detected by reachability flags.
///
/// - ethernetOrWiFi: The connection type is either over Ethernet or WiFi.
/// - wwan:           The connection type is a WWAN connection.
public enum ConnectionType {
    case ethernetOrWiFi
    case wwan
}
14.1 網(wǎng)絡(luò)是否連接
    /// 檢查網(wǎng)絡(luò)連接,判斷網(wǎng)絡(luò)類型(ethernetOrWiFi / wwan)
    /// 參考: https://github.com/Alamofire/Alamofire
    /// - Returns: (check connected, Network Reachability Status)
    open static func connectedToNetwork() -> (connected:Bool,connectionType:NetworkReachabilityStatus) {
        
        var zeroAddress = sockaddr_in()
        zeroAddress.sin_len = UInt8(MemoryLayout<sockaddr_in>.size)
        zeroAddress.sin_family = sa_family_t(AF_INET)
        
        guard let defaultRouteReachability = withUnsafePointer(to: &zeroAddress, {
            $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
                SCNetworkReachabilityCreateWithAddress(nil, $0)
            }
        }) else {
            return (false,.unknown)
        }
        
        var flags: SCNetworkReachabilityFlags = []
        if !SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) {
            return (false,.unknown)
        }
        
        let conType = flags.contains(.isWWAN) ?  ConnectionType.wwan : ConnectionType.ethernetOrWiFi
        
        let isReachable = flags.contains(.reachable)
        let needsConnection = flags.contains(.connectionRequired)
        let canConnectAutomatically = flags.contains(.connectionOnDemand) || flags.contains(.connectionOnTraffic)
        let canConnectWithoutUserInteraction = canConnectAutomatically && !flags.contains(.interventionRequired)
        
        guard isReachable && (!needsConnection || canConnectWithoutUserInteraction) else {
            return (false,.notReachable)
        }
        
        return (true,.reachable(conType))
    }
14.2 網(wǎng)絡(luò)連接類型(2G简十、3G、4G撬腾、WIFI)
    /// 網(wǎng)絡(luò)狀態(tài)(2G勺远、3G、4G时鸵、WIFI)
    ///
    /// - Returns: String
    open static func getNetWorkTypee() -> String {
        let result = "未知網(wǎng)絡(luò)"
        let info = CTTelephonyNetworkInfo()
        let netWork = connectedToNetwork()
        
        guard netWork.connected else {
            return "未連接網(wǎng)絡(luò)"
        }
        
        switch netWork.connectionType {
        case .reachable(.ethernetOrWiFi):
            return "WIFI"
        case .reachable(.wwan):
            let currentRadioAccessTechnology = info.currentRadioAccessTechnology
            guard currentRadioAccessTechnology != nil else {
                return result
            }
            
            if currentRadioAccessTechnology! == CTRadioAccessTechnologyLTE {
                return "4G"
            }else if (currentRadioAccessTechnology! == CTRadioAccessTechnologyEdge) || (currentRadioAccessTechnology! == CTRadioAccessTechnologyGPRS) {
                return "2G"
            }else {
                return "3G"
            }
            
        default:
            return result
        }
    }

參考

Alamofire
SystemKit
Models

Demo

Demo

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市厅瞎,隨后出現(xiàn)的幾起案子饰潜,更是在濱河造成了極大的恐慌,老刑警劉巖和簸,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件彭雾,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡锁保,警方通過(guò)查閱死者的電腦和手機(jī)薯酝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)爽柒,“玉大人吴菠,你說(shuō)我怎么就攤上這事『拼澹” “怎么了做葵?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)心墅。 經(jīng)常有香客問(wèn)我酿矢,道長(zhǎng),這世上最難降的妖魔是什么怎燥? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任瘫筐,我火速辦了婚禮,結(jié)果婚禮上铐姚,老公的妹妹穿的比我還像新娘策肝。我一直安慰自己,他們只是感情好谦屑,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布驳糯。 她就那樣靜靜地躺著,像睡著了一般氢橙。 火紅的嫁衣襯著肌膚如雪酝枢。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,007評(píng)論 1 284
  • 那天悍手,我揣著相機(jī)與錄音帘睦,去河邊找鬼袍患。 笑死,一個(gè)胖子當(dāng)著我的面吹牛竣付,可吹牛的內(nèi)容都是我干的诡延。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼古胆,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼肆良!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起逸绎,我...
    開(kāi)封第一講書(shū)人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤惹恃,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后棺牧,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體巫糙,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年颊乘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了参淹。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡乏悄,死狀恐怖浙值,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情檩小,我是刑警寧澤亥鸠,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站识啦,受9級(jí)特大地震影響负蚊,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜颓哮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一家妆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧冕茅,春花似錦伤极、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至乍楚,卻和暖如春当编,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背徒溪。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工忿偷, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留金顿,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓鲤桥,卻偏偏與公主長(zhǎng)得像揍拆,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子茶凳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容