首页 > 解决方案 > NWEndPoint:从另一个VC获取网关IP地址时返回nil

问题描述

我已经找到了这个问题的解决方案,请参见下面的答案。

我定义了一个函数getGatewayInfo()来获取网关 IP 地址并将其返回给调用者。print(NetworkUtility().getGatewayInfo())但是当我从其他 VC调用这个函数时viewDidLoad,它返回 nil。

从日志中,我可以看到gatewayIPAddress已从 中获取值NWEndpoint,即192.168.1.1. 但是,它返回 nil 并打印出“未找到网关 IP 地址!”。你能给我一些提示我哪里做错了吗?

Gateway IP address is not found!
Gateway: 192.168.1.1
import UIKit
import Network

class NetworkUtility {
    var gatewayIPAddress: String?
    
    func getGatewayInfo() -> String {
        let monitor = NWPathMonitor(requiredInterfaceType: .wifi)
        monitor.pathUpdateHandler = { path in
            let endpoint = path.gateways[0]
            
            switch endpoint {
            case .hostPort(let host, _):
                self.gatewayIPAddress = host.debugDescription
                print("Gateway: \(self.gatewayIPAddress!)")
            default:
                break
            }
        }
        monitor.start(queue: DispatchQueue(label: "nwpathmonitor.queue"))
        
        if let gatewayIPAddress = gatewayIPAddress {
            return gatewayIPAddress
        } else {
            return "Gateway IP address is not found!"
        }
    }
}

标签: iosswiftuikitip-addressnwpathmonitor

解决方案


这里的问题是 path in 中的 handler 代码(闭包)monitor.pathUpdateHandler是异步执行的,所以前面代码中的 return 语句会在它之前执行。最终,返回的参数是nil.

而且由于我们不知道闭包中的代码何时会像一些网络请求一样完成。所以我们不能在这个函数中使用返回方法。相反,我们应该使用另一个完成处理程序来返回参数值,即回调。就像我们在一些 JSON 请求函数中所做的那样。

涉及另一个completionHandler以防返回字符串参数的代码:

func getGatewayInfo(completionHandler: @escaping (String) -> ()) {
    let monitor = NWPathMonitor(requiredInterfaceType: .wifi)
    monitor.pathUpdateHandler = { path in
        if let endpoint = path.gateways.first {
            switch endpoint {
            case .hostPort(let host, _):
                let remoteHost = host.debugDescription
                print("Gateway: \(remoteHost)")
                // Use callback here to return the ip address to the caller
                completionHandler(remoteHost)
            default:
                break
            }
        } else {
            print("Wifi connection may be dropped.")
        }
    }
    monitor.start(queue: DispatchQueue(label: "nwpathmonitor.queue"))
}

呼叫者,召集者:

override func viewDidLoad() {
    super.viewDidLoad()
    title = pageTitle
    
    // Receive remoteHost from callback parameter(aka. gateway ip address)
    NetworkUtility().getGatewayInfo { (remoteHost) in
        print("remote: \(remoteHost)")
        DispatchQueue.main.async {
            self.gwIPAddress.text = remoteHost
        }
    }
}

推荐阅读