Reachability:它是什么,网络可用性检查库

作者: IT Sectr 发布日期: 2026-03-11 阅读时间: 10 分钟

Reachability — 一个基于SystemConfiguration框架构建的iOS和macOS库,可以检查互联网连接的可用性并跟踪其变化。根据Apple Developer Documentation (2025),Reachability使用SCNetworkReachability进行异步网络监控。Reachability库长期以来一直是iOS项目的标准,直到原生NWPathMonitor的出现。

要点

  • Reachability — C框架SystemConfiguration的封装,用于监控iOS和macOS中的网络可用性。
  • SCNetworkReachability — 低层C-API,检查远程主机或地址的可达性。
  • 连接类型 — Reachability区分Wi-Fi和移动数据(WWAN)以适应应用程序的行为。
  • 通知 — 通过SCNetworkReachabilitySetCallback,库使用RunLoop订阅网络变化。
  • NWPathMonitor — Reachability的现代替代品,从iOS 12开始可用并获Apple推荐。

什么是Reachability?

Reachability — 是Apple的一个示例库,演示了使用SystemConfiguration框架进行网络监控。源代码作为示例发布在Apple Developer Documentation中,但社区已将其接受为iOS项目中检查连接的标准工具。

该库基于SCNetworkReachability工作——来自SystemConfiguration的C函数,评估远程主机或IP地址的可达性。创建Reachability时,指定主机名(如google.com)或IP地址,库会异步检查该主机是否可通过设备当前的网络接口访问。

Reachability的流行度归功于其简单性:只需创建实例,通过NotificationCenter订阅通知,并监听kReachabilityChangedNotification。作为响应,应用程序接收到状态:NotReachable、ReachableViaWiFi或ReachableViaWWAN(移动数据)。

库的历史和状态

Reachability首次出现在iPhone OS 2(2008)中,与SystemConfiguration框架一起。在十年间,它是iOS中唯一的原生网络监控方式。随iOS 12和Network框架的发布,Apple推荐NWPathMonitor作为替代品,但Reachability仍然受支持。

许多第三方封装——AFNetworking、Alamofire、AshleyDodd/Reachability.swift——使用SCNetworkReachability内部机制。这些库添加了便捷的Swift/Objective-C接口、状态缓存和线程安全的回调,保持相同的SystemConfiguration基础。

Reachability内部工作原理

Reachability的主要机制——SCNetworkReachabilityCreateWithName函数,为指定的主机创建跟踪对象。然后调用SCNetworkReachabilityGetFlags——同步检查,返回带有当前网络状态的SCNetworkReachabilityFlags位码。

对于异步监控,使用SCNetworkReachabilitySetCallback,注册C回调函数。当主机可达性状态改变时,回调在当前的RunLoop上执行。Reachability将这个C回调封装到Objective-C方法中,并通过NotificationCenter发送通知。

swift
import SystemConfiguration

class Reachability {
    private var reachabilityRef: SCNetworkReachability?

    init?(hostname: String) {
        reachabilityRef = SCNetworkReachabilityCreateWithName(
            nil, hostname
        )
    }

    func checkReachability() -> Bool {
        var flags = SCNetworkReachabilityFlags()
        SCNetworkReachabilityGetFlags(
            reachabilityRef!, &flags
        )
        return isReachable(with: flags)
    }

    private func isReachable(with flags: SCNetworkReachabilityFlags) -> Bool {
        let reachable = flags.contains(.reachable)
        let connectionRequired = flags.contains(.connectionRequired)
        return reachable && !connectionRequired
    }
}

网络可达性标志

SCNetworkReachabilityFlags——编码网络状态的位码。kSCNetworkReachabilityFlagsReachable标志表示主机可达。kSCNetworkReachabilityFlagsConnectionRequired——需要建立通信才能连接。标志的组合确定应用程序是否可以发送数据。

附加标志:kSCNetworkReachabilityFlagsIsWWAN——通过移动网络连接(iOS),kSCNetworkReachabilityFlagsInterventionRequired——需要用户干预(如VPN)。Reachability考虑这些标志以确定接口类型。

Reachability使用示例

在iOS应用程序中使用Reachability的标准模式包括创建实例、订阅通知以及对状态变化做出反应。下面的示例展示了与NotificationCenter的集成,用于在网络变化时更新UI。

swift
import Reachability
import UIKit

class ViewController: UIViewController {
    var reachability: Reachability?

    override func viewDidLoad() {
        super.viewDidLoad()
        reachability = Reachability(hostname: "google.com")
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(reachabilityChanged),
            name: .reachabilityChanged,
            object: nil
        )
        reachability?.startNotifier()
    }

    @objc func reachabilityChanged(notification: Notification) {
        if let reachability = notification.object as? Reachability {
            switch reachability.connection {
            case .wifi:
                print("通过Wi-Fi连接")
            case .cellular:
                print("通过移动网络连接")
            case .unavailable:
                print("未连接")
            }
        }
    }
}

请求前的网络检查

在执行HTTP请求之前,可以同步检查网络可用性:reachability.connection != .unavailable。这不能保证请求成功(服务器可能不可用),但可以避免定然失败的请求并改善用户体验——应用程序在离线模式下不显示加载圆圈。

为了更精确的检查,将Reachability与URLSession超时结合。如果Reachability显示可达,但请求在超时时间内未执行——问题可能出在服务器端或限制网关。在这种情况下,可以向用户显示服务器不可用的消息。

Reachability中的连接类型

Reachability区分三种主要连接状态:Wi-Fi、移动数据(WWAN)和不可用。WWAN包括所有类型的移动通信——2G、3G、4G/LTE、5G。该库不提供WWAN内的详细信息,因此区分4G和5G需要CoreTelephony。

状态SCNetwork标志描述
ReachableViaWiFiReachable + !IsWWAN通过Wi-Fi网络连接,可访问主机
ReachableViaWWANReachable + IsWWAN通过移动网络连接(2G-5G)
NotReachable!Reachable主机无法通过任何接口访问
ConnectionRequiredReachable + ConnectionRequired需要建立连接(VPN、PPPoE)

按网络类型划分的Reachability局限性

Reachability不区分Ethernet、VPN隧道或multipath连接——所有非WWAN接口都被分类为Wi-Fi。这一局限性与SystemConfiguration的架构有关,它在基本分类之外不提供有关网络接口的详细信息

要确定移动通信的具体类型(4G vs 5G),需要来自CoreTelephony的CTTelephonyNetworkInfo。将Reachability与CoreTelephony结合可以让应用程序选择内容质量:在5G下播放4K流媒体,在4G/LTE下播放HD,在3G下播放SD或仅播放音频。

从Reachability迁移到NWPathMonitor

Apple建议在所有新项目中将Reachability替换为NWPathMonitor,从iOS 12开始。主要原因是NWPathMonitor是现代Network框架的一部分,用Swift编写,支持Combine,并提供关于网络路径的详细信息,无需C兼容性。

迁移过程包括将SCNetworkReachability替换为NWPathMonitor,从NotificationCenter迁移到pathUpdateHandler closure或Combine publisher。网络状态处理的算法和逻辑保持不变——仅监控API发生变化。

swift
protocol NetworkMonitorProtocol {
    var isReachable: Bool { get }
    var connectionType: ConnectionType { get }
    func startMonitoring()
    func stopMonitoring()
}

enum ConnectionType {
    case wifi, cellular, ethernet, unavailable
}

// 使用NWPathMonitor的现代实现
class ModernNetworkMonitor: NetworkMonitorProtocol {
    private let monitor = NWPathMonitor()
    private let queue = DispatchQueue("Network")
    private var currentPath: NWPath?

    var isReachable: Bool {
        currentPath?.status == .satisfied
    }

    func startMonitoring() {
        monitor.pathUpdateHandler = { [weak self] path in
            self?.currentPath = path
        }
        monitor.start(on: queue)
    }

    func stopMonitoring() {
        monitor.cancel()
    }
}

迁移建议

对于基础支持iOS 12+的项目,将Reachability完全替换为NWPathMonitor。对于支持iOS 11的项目,使用条件编译#available(iOS 12, *),将NWPathMonitor作为主要方案,Reachability作为备用。这样可以逐步迁移,而不会丢失对旧设备的支持。

迁移的主要优势是网络路径的详细信息。NWPathMonitor不仅报告“可用/不可用”,还提供每个接口的类型、成本、优先级、代理和VPN支持。这为开发人员提供了更多数据,以将应用程序的行为适应当前网络条件。

常见问题

Reachability支持的最低iOS版本是多少?

基于SCNetworkReachability的Reachability从iPhone OS 2(iOS 2)开始可用。该库在所有iOS版本上都可以工作,包括当前版本。局限性不涉及操作系统版本,而是信息的详细程度——在旧版本上没有 4G 和 5G 的区分。

Reachability与简单的ping检查有什么不同?

Reachability使用SCNetworkReachability——一种系统服务,在不发送数据包的情况下,在网络堆栈层面评估主机的可达性。Ping发送ICMP数据包并消耗流量,还可能被防火墙拦截。Reachability更快更安全,适合频繁检查。

可以在SwiftUI项目中使用Reachability吗?

可以,Reachability通过ObservableObject或Combine在SwiftUI中工作。将其封装到订阅了NotificationCenter的类中,并通过@Published发布状态。对于新的SwiftUI项目,我们建议使用带Combine publisher的NWPathMonitor来实现View的响应式更新。

Reachability如何区分Wi-Fi和移动数据?

Reachability检查SCNetworkReachabilityFlags位码中的kSCNetworkReachabilityFlagsIsWWAN标志。如果该标志被设置——通过移动网络(WWAN)连接,否则且主机可达——通过Wi-Fi连接。这是不使用CoreTelephony区分类型的唯一方法。

为什么Reachability显示可用,但请求不工作?

SCNetworkReachability在网络层检查主机的可达性,但不保证高层协议的工作。可能的原因:限制网关、DNS拦截、代理服务器或防火墙。Reachability是第一层过滤,但不能替代真正的HTTP请求。

总结

  • Reachability — 基于SystemConfiguration的iOS网络监控库,通过SCNetworkReachability C-API工作。
  • 三种状态 — Wi-Fi、移动数据(WWAN)和不可用——由SCNetworkReachabilityFlags的位标志确定。
  • 异步通知 通过SCNetworkReachabilitySetCallback使用RunLoop和NotificationCenter实现。
  • 局限性 — Reachability不区分4G/5G、VPN、Ethernet,且不提供流量成本信息。
  • NWPathMonitor — 适用于iOS 12+的Reachability现代替代品,提供包含类型、成本和multipath的详细NWPath。
  • 迁移 包括将SCNetworkReachability替换为NWPathMonitor,通过NetworkMonitorProtocol协议保持逻辑。
  • Reachability仍然 是支持iOS 11及更低版本的项目或快速同步检查所需要的。

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读