如何在iOS或macOS上检查网络连接是否正常?

1406

我想通过使用 Cocoa Touch 库来检查 iOS 上是否有互联网连接,或者使用 Cocoa 库在 macOS 上进行检查。

我用 NSURL 想到了一种方法来实现这一点。但是我觉得这种方法有点不可靠(因为即使谷歌某天挂了,依赖于第三方也是不好的),而且如果谷歌不能响应,我可以检查其他网站的响应,但这似乎是浪费并增加了额外负担。

- (BOOL)connectedToInternet {
    NSString *URLString = [NSString stringWithContentsOfURL:[NSURL URLWithString:@"http://www.google.com"]];
    return ( URLString != NULL ) ? YES : NO;
}

我所做的是否不好,(更不用提 stringWithContentsOfURL 在 iOS 3.0 和 macOS 10.4 中已被弃用),如果不好,有什么更好的方法可以实现这个功能吗?


12
建议使用 return !!URLString 或者 return URLString != nil,甚至比 return (BOOL)URLString; 更好。这样做可以使代码更加简洁易懂,而且表达的意思与原文一致。 - user529758
3
我不知道你的使用情况,但如果可能的话,最好尝试发送请求并处理任何出现的错误,比如缺少连接。如果你无法这样做,那么在这种情况下有很多好的建议。 - Ken
2
你的解决方案很聪明,我更喜欢它。你也可以使用 NSString *URLString = [NSString stringWithContentsOfURL:[NSURL URLWithString:@"https://twitter.com/getibox"] encoding:NSUTF8StringEncoding error:nil]; 来消除烦人的警告。 - Abdelrahman Eid
4
请尝试使用下面链接中的Reachability类,它适用于您的情况。https://github.com/tonymillion/Reachability - Dhaval H. Nena
4
针对最近看到这个回答的人:https://dev59.com/NGoy5IYBdhLWcg3wCpsz#8813279 - afollestad
显示剩余4条评论
46个回答

2

此答案取代其他答案。请参见:https://developer.apple.com/documentation/network/nwpathmonitor - Cenk Bilgen

1

Alamofire

我知道问题要求提供Coca Touch解决方案,但我想为那些搜索iOS上检查互联网连接并希望有更多选项的人提供一种解决方案。

如果您已经在使用Alamofire,您可以从中获得以下好处。

您可以将以下类添加到您的应用程序中,并调用MNNetworkUtils.main.isConnected()以获取一个布尔值,表示它是否已连接。

#import Alamofire

class MNNetworkUtils {
  static let main = MNNetworkUtils()
  init() {
    manager = NetworkReachabilityManager(host: "google.com")
    listenForReachability()
  }

  private let manager: NetworkReachabilityManager?
  private var reachable: Bool = false
  private func listenForReachability() {
    self.manager?.listener = { [unowned self] status in
      switch status {
      case .notReachable:
        self.reachable = false
      case .reachable(_), .unknown:
        self.reachable = true
      }
    }
    self.manager?.startListening()
  }

  func isConnected() -> Bool {
    return reachable
  }
}

这是一个singleton类。每次用户连接或断开网络时,它都会正确地覆盖self.reachable,因为我们在单例初始化时开始监听NetworkReachabilityManager
另外,为了监控可达性,您需要提供一个主机。目前,我正在使用google.com,但如果需要可以随意更改为任何其他主机或您自己的主机。将类名和文件名更改为与您的项目匹配的任何内容。

请问您能帮忙解释一下上述代码的用法吗?如何使用它? - Khadija Daruwala
@PersianBlue 你可以将以下类添加到你的应用程序中,然后调用MNNetworkUtils.main.isConnected()来获取它是否已连接的布尔值。(这已经在答案中提到了) - nuynait
是的,我已经尝试过了,但无论互联网的状态如何,它总是给我错误的结果。 - Khadija Daruwala
你好,我能检测到网络突然中断吗? - famfamfam

1
请尝试这个。它会帮助你(Swift 4)
  1. Install Reachability via CocoaPods or Carthage: Reachability

  2. Import Reachability and use it in the Network class

    import Reachability
    
    class Network {
    
       private let internetReachability : Reachability?
       var isReachable : Bool = false
    
       init() {
    
           self.internetReachability = Reachability.init()
           do{
               try self.internetReachability?.startNotifier()
               NotificationCenter.default.addObserver(self, selector: #selector(self.handleNetworkChange), name: .reachabilityChanged, object: internetReachability)
           }
           catch {
            print("could not start reachability notifier")
           }
       }
    
       @objc private func handleNetworkChange(notify: Notification) {
    
           let reachability = notify.object as! Reachability
           if reachability.connection != .none {
               self.isReachable = true
           }
           else {
               self.isReachable = false
           }
           print("Internet Connected : \(self.isReachable)") //Print Status of Network Connection
       }
    }
    
  3. Use like the below where you need it.

    var networkOBJ = Network()
    // Use "networkOBJ.isReachable" for Network Status
    print(networkOBJ.isReachable)
    

1
//
//  Connectivity.swift
// 
//
//  Created by Kausik Jati on 17/07/20.
// 
//

import Foundation
import Network

enum ConnectionState: String {
    case notConnected = "Internet connection not avalable"
    case connected = "Internet connection avalable"
    case slowConnection = "Internet connection poor"
}
protocol ConnectivityDelegate: class {
    func checkInternetConnection(_ state: ConnectionState, isLowDataMode: Bool)
}
class Connectivity: NSObject {
    private let monitor = NWPathMonitor()
    weak var delegate: ConnectivityDelegate? = nil
    private let queue = DispatchQueue.global(qos: .background)
    private var isLowDataMode = false
    static let instance = Connectivity()
private override init() {
    super.init()
    monitor.start(queue: queue)
    startMonitorNetwork()
}
private func startMonitorNetwork() {
    monitor.pathUpdateHandler = { path in
        if #available(iOS 13.0, *) {
            self.isLowDataMode = path.isConstrained
        } else {
            // Fallback on earlier versions
            self.isLowDataMode = false
        }
        
        if path.status == .requiresConnection {
            print("requiresConnection")
                self.delegate?.checkInternetConnection(.slowConnection, isLowDataMode: self.isLowDataMode)
        } else if path.status == .satisfied {
            print("satisfied")
                 self.delegate?.checkInternetConnection(.connected, isLowDataMode: self.isLowDataMode)
        } else if path.status == .unsatisfied {
            print("unsatisfied")
                self.delegate?.checkInternetConnection(.notConnected, isLowDataMode: self.isLowDataMode)
            }
        }
    
    }
    func stopMonitorNetwork() {
        monitor.cancel()
    }
}

2
请添加描述 - meewog
Connectivity.instance.delegate = self 扩展 ViewController: ConnectivityDelegate { func checkInternetConnection(_ state: ConnectionState, isLowDataMode: Bool) {}} - Kausik Jati

0

Swift 5,Alamofire,主机

// Session reference
var alamofireSessionManager: Session!

func checkHostReachable(completionHandler: @escaping (_ isReachable:Bool) -> Void) {
    let configuration = URLSessionConfiguration.default
    configuration.timeoutIntervalForRequest = 1
    configuration.timeoutIntervalForResource = 1
    configuration.requestCachePolicy = .reloadIgnoringLocalCacheData

    alamofireSessionManager = Session(configuration: configuration)

    alamofireSessionManager.request("https://google.com").response { response in
        completionHandler(response.response?.statusCode == 200)
    }
}

// Using
checkHostReachable() { (isReachable) in
    print("isReachable:\(isReachable)")
}

-2

试试这个:

- (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error


if ([self.delegate respondsToSelector:@selector(getErrorResponse:)]) {
    [self.delegate performSelector:@selector(getErrorResponse:) withObject:@"No Network Connection"];
}

UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"BMC" message:@"No Network Connection" delegate:self cancelButtonTitle:nil otherButtonTitles:@"OK",nil];
[alertView show];

}


1
至少添加一个解释,说明这段代码是做什么的,以及它如何解决问题。 - Mark Rotteveel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接