How to detect if the internet connection is over WiFi or Ethernet?

前端 未结 3 1321
旧时难觅i
旧时难觅i 2021-02-09 00:50

Is there a way to open network settings programmatically? Closest thing I know is opening the main settings page:

let settingsURL = NSURL(string: UIApplicationOp         


        
相关标签:
3条回答
  • 2021-02-09 01:21

    For iOS 12.0+, tvOS 12.0+, macOS 10.14+ and watchOS 5.0+ apps you can use NWPathMonitor to solve the problem that you described in your question. Add this code to your application(_:didFinishLaunchingWithOptions:) implementation (Swift 5.1.3/Xcode 11.3.1):

    let pathMonitor = NWPathMonitor()
    pathMonitor.pathUpdateHandler = { path in
        if path.status == .satisfied {
            if path.usesInterfaceType(.wifi) {
                print("wifi")
            } else if path.usesInterfaceType(.cellular) {
                print("cellular")
            } else if path.usesInterfaceType(.wiredEthernet) {
                print("wiredEthernet")
            } else if path.usesInterfaceType(.loopback) {
                print("loopback")
            } else if path.usesInterfaceType(.other) {
                print("other")
            }
        } else {
            print("not connected")
        }
    }
    pathMonitor.start(queue: .global(qos: .background))
    

    And don't forget to add import Network to the top of the file.

    0 讨论(0)
  • 2021-02-09 01:28

    You can use Reachability API.

    let reachability: Reachability = Reachability.reachabilityForInternetConnection()
    (reachability.currentReachabilityStatus().value == ReachableViaWiFi.value) // For WiFi
    (reachability.currentReachabilityStatus().value == ReachableViaWWAN.value) // For WWAN
    (reachability.currentReachabilityStatus().value == NotReachable.value) // For No Internet
    
    0 讨论(0)
  • 2021-02-09 01:35

    The way to detect this is to look at the name of the network interfaces. For Mac and Apple TV, en0 and en1 refer to the wired and wireless interfaces respectively.

    Add this to your bridging header (or create one if needed):

    #include <ifaddrs.h>
    #include <net/if_dl.h>
    

    Then use this Swift code to get the information you need:

    struct Networking {
    
        enum NetworkInterfaceType: String, CustomStringConvertible {
            case Ethernet = "en0"
            case Wifi = "en1"
            case Unknown = ""
    
            var description: String {
                switch self {
                case .Ethernet:
                    return "Ethernet"
                case .Wifi:
                    return "Wifi"
                case .Unknown:
                    return "Unknown"
                }
            }
        }
    
        static var networkInterfaceType: NetworkInterfaceType {
            if let name = Networking().getInterfaces().first?.name, let type = NetworkInterfaceType(rawValue: name) {
                return type
            }
    
            return .Unknown
        }
    
        static var isConnectedByEthernet: Bool {
            let networking = Networking()
            for addr in networking.getInterfaces() {
                if addr.name == NetworkInterfaceType.Ethernet.rawValue {
                    return true
                }
            }
            return false
        }
    
        static var isConnectedByWiFi: Bool {
            let networking = Networking()
            for addr in networking.getInterfaces() {
                if addr.name == NetworkInterfaceType.Wifi.rawValue {
                    return true
                }
            }
            return false
        }
    
        // Credit to Martin R http://stackoverflow.com/a/34016247/600753 for this lovely code
        // New Swift 3 implementation needed upated to replace unsafepointer calls with .withMemoryRebound
        func getInterfaces() -> [(name : String, addr: String, mac : String)] {
    
            var addresses = [(name : String, addr: String, mac : String)]()
            var nameToMac = [ 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)
                if var addr = ptr.pointee.ifa_addr {
                    let name = String(cString: ptr.pointee.ifa_name)
    
                    // Check for running IPv4, IPv6 interfaces. Skip the loopback interface.
                    if (flags & (IFF_UP|IFF_RUNNING|IFF_LOOPBACK)) == (IFF_UP|IFF_RUNNING) {
                        switch Int32(addr.pointee.sa_family) {
                        case AF_LINK:
                            nameToMac[name] = withUnsafePointer(to: &addr) { unsafeAddr in
                                unsafeAddr.withMemoryRebound(to: sockaddr_dl.self, capacity: 1) { dl in
                                    dl.withMemoryRebound(to: Int8.self, capacity: 1) { dll in
                                        let lladdr = UnsafeRawBufferPointer(start: dll + 8 + Int(dl.pointee.sdl_nlen), count: Int(dl.pointee.sdl_alen))
    
                                        if lladdr.count == 6 {
                                            return lladdr.map { String(format:"%02hhx", $0)}.joined(separator: ":")
                                        } else {
                                            return nil
                                        }
                                    }
                                }
                            }
    
                        case AF_INET, AF_INET6:
                            // Convert interface address to a human readable string:
                            var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
                            if (getnameinfo(addr, socklen_t(addr.pointee.sa_len),
                                            &hostname, socklen_t(hostname.count),
                                            nil, socklen_t(0), NI_NUMERICHOST) == 0) {
                                let address = String(cString: hostname)
                                addresses.append( (name: name, addr: address, mac : "") )
                            }
                        default:
                            break
                        }
                    }
                }
            }
    
            freeifaddrs(ifaddr)
    
            // Now add the mac address to the tuples:
            for (i, addr) in addresses.enumerated() {
                if let mac = nameToMac[addr.name] {
                    addresses[i] = (name: addr.name, addr: addr.addr, mac : mac)
                }
            }
    
            return addresses
        }
    }
    

    Usage is:

    debugPrint(Networking.networkInterfaceType)
    

    Or:

    switch Networking.networkInterfaceType {
    case .Ethernet:
        // do something
        break
    
    case .Wifi:
        // do something else
        break
    
    default:
        break
    }
    
    0 讨论(0)
提交回复
热议问题