我的编程空间,编程开发者的网络收藏夹
学习永远不晚

iOS 12+ 中检测网络访问的方法

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

iOS 12+ 中检测网络访问的方法

我最近写了一篇文章,来介绍 iOS 在连接新的 Wi-Fi 网络时,如何在弹出一个 web view 以让用户登录或注册之前,检测 Captive Portals (强制网络门户)。如果你连接过诸如酒店、酒吧或咖啡店等地的公共 Wi-Fi 网络,对这个应该会比较熟悉。如果你不熟悉 iOS 中 Captive Portals 的工作方式,可以查看 Solving the Captive Portal Problem on iOS 这篇文章,以了解一些背景知识。

多年来,Apple 的 Reachability 示例程序一直被用作 App 中检测网络访问的基础代码。搜索 Cocoapods.org 将会看到一个很长的第三方库列表,这些库基本上都是基于 Reachability,并考虑了 ARC 的支持或 Swift 的兼容等问题。 在 WWDC 2018 上,Apple 介绍了 iOS 12 中的一个新的框架:Network.framework,该框架包含了一个 NWPathMonitor 类。这个类为我们提供了一种监视网络状态变化的方法,而无需包含第三方库或 Apple 示例代码。

使用

只需简单导入 Network 框架,便可以使用 NWPathMonitor 类,如下创建一个 NWPathMonitor 实例:


let monitor = NWPathMonitor()

如果你只对某个特定网络适配器的状态变更感兴趣,例如 Wi-Fi,则可以使用 init(requiredInterfaceType:) 初始化方法,并提供 NWInterface.InterfaceType 值作为参数,来实例化 NWPathMonitor 对象,以监听指定类型的网络适配器,例如:


let monitor = NWPathMonitor(requiredInterfaceType: .wifi)

您需要确保在某处保留对 NWPathMonitor 对象的引用(例如使用 strong 属性),否则 ARC 可能会释放 NWPathMonitor 对象,从而导致指定的回调无法被调用。

可监控的网络类型包括:

  • cellular
  • loopback
  • other (对于虚拟或未确定的网络类型)
  • wifi
  • wiredEthernet

要获取状态更改的通知,需要为 pathUpdateHandler 属性指定一个回调,该回调将在网络接口发生状态更改时调用。例如,你的手机网络从蜂窝网络切换到 Wi-Fi 网络。然后,每当发生状态更改时,将返回一个 NWPath 实例,可以使用该实例以确定后续的操作,如下代码:


monitor.pathUpdateHandler = { path in
  if path.status == .satisfied {
    print("Connected")
  }
}

使用无参初始化方法与使用指定网络适配器的初始化方法的不同点是:返回的 NWPathobject 对象的 status 属性是否是 satisfied。例如,你只想监听蜂窝网络,而你的手机连接的是 Wi-Fi 网络,则当 Wi-Fi 网络状态发生变化时,并不会调用回调方法,并且 path 的 status 也会保持 unsatisfied 状态,因为手机没有使用指定的网络连接。所以,如果你只想知道是否有网络连接,无论是 Wi-Fi 还是蜂窝,则最好使用无参数的初始化方法。

一个有趣的问题是,NWPath 在 iOS 12 中是作为 Network 框架的一部分,而实际上在 iOS 9 中就有它的身影,不过是在 NetworkExtension.framework,两者之间有一些细微差别。

可以查询返回的 NWPath 对象,以查看设备的网络适配器的状态信息。另一个更有趣的属性是 isExpensive,它标识网络接口返回的数据收费是否昂贵,如使用蜂窝数据。我们同样可以查询是否支持 DNS、IPv4 或 IPv6。我们可以调用 usesInterfaceType 方法,来查看哪个接口改变了状态并触发回调:


let isCellular: Bool = path.usesInterfaceType(.cellular)

使用 NWPathMonitor 有点类似于使用其他 iOS API,例如 CLLocationManager,我们需要调用 start 方法以便开始接收更新,然后在完成后调用对应的 stop 方法。NWPathMonitor 的 start 方法要求我们为对象提供一个队列来执行其工作:


let queue = DispatchQueue.global(qos: .background)
monitor.start(queue: queue)

当我们完成监听状态的变化时,我们只需在调用 cancel() 方法。请注意,目前在 NWPathMonitor 上调用 cancel 后,我们无法再次启动监听,而是需要实例化一个新的 NWPathMonitor 实例。 请注意,如果在调用 start() 之前访问 NWPathMonitor 的 currentPath 属性,将返回 nil。实际上,如果你打印返回到更新回调的 path,如下所示:


monitor.pathUpdateHandler = { path in
  print(path)
}

则会打印以下内容:

Optional(satisfied (Path is satisfied), interface: en0, scoped, ipv4, ipv6, dns)

这表明此处返回的 NWPaths 和 currentPath 属性是可选项,尽管 API 没有明确说明(我们可以推断返回的 NWPath 引用是桥接到 Swift 的 Objective-C 指针)。

Captive Portals

Captive Portal 是在公共 Wi-Fi 热点连接时显示的网页,通常用于在授权访问 Internet(或访问其他网络资源)之前强制登录、注册或支付。在之前的一篇博客中,我谈到了从 App 开发的的角度来看,Reachability 看起来好像没什么问题,但实际上由于有 Captive Portals,它并不能很好完成任务。这可能导致 App 无法正常工作甚至于崩溃 -- 因为 App 可能期望从 RESTful API 中获取一些 JSON 数据,却从 Captive Portals 获取到了一些 HTML。

我之前很好奇 NWPathMonitor 在检测网络连接方面是否比 Reachability 有所改进。NWPath.Status 枚举确实提供了三种情况 -- satisfied、 unsatisfied 和 requiresConnection。不幸的是,Network.framework 的开发者文档并未提供这些枚举值的使用说明,而如果我们查看 NetworkExtension.framework 文档,其中的 NWPathStatus 对象提供了 satisfiable 枚举值,里面有一些相关文档描述:

The path is not currently satisfied, but may become satisfied upon a connection attempt. This can be due to a service, such as a VPN or a cellular data connection not being activated.

requiresConnection 枚举值似乎类似于 NWPathStatus 对象的 satisfiable 值。 好消息是 NWPathMonitor 通常只在 captive portal 协商之后通知 path 被设置为 satisfiable 状态,即在弹出 web view 且用户登录后。而在没有弹出 captive portal 的情况下,将向用户显示一个 Action Sheet,提供了 Use Without Internet 和 Use Other Network 选项。如果用户选择了 Use Without Internet,则 NWPathMonitor 返回的 path 的状态是 satisfied,即便实际上并没有连网。

通过使用 Charles 做的一些实验,我发现除非选择 Use Without Internet,否则在初始化 Wi-Fi 网络连接的同时中断连接的情况下,NWPathMonitor 没有报告 NWPath 的 Status 被置为 statisfied。但是,如果网络连接已恢复,但随后被删除,则并不能检测到这种变更,并且 path 的状态未依然是 satisfied。如果用户仅在火车或酒店上支付一小时的互联网访问费用,这种情况是可能发生的。

Connectivity

Connectivity 是一个 MIT 许可的开源框架,其目的是复用 iOS 现有的检测 captive portal 的方法。它允许在 iOS 8+ 上使用 Reachability 准确检测真正的 Internet 连接,这意味着在无法使用 NWPathMonitor 时,我们可以使用这个方法。并且在 iOS 12 上,Connectivity 使用了 NWPathMonitor 来提供更高的准确度。

Connectivity 已经提供了对 NWPathMonitor 的支持,可用于 iOS 12+ 系统。如果 framework 属性设置为 network,则会使用 Network 框架来替代 SystemConfiguration 框架(Reachability),以监听网络适配器的状态变更。


let connectivity = Connectivity()
connectivity.framework = .network

在网络适配器中的状态更改后,Connectivity 会执行大量检查以确定 Internet 访问是否可用。另外还有一个轮询选项,可以用来轮询网络是否可用,即使状态并未发生改变。可以通过设置 isPollingEnabled = true 并将 pollingInterval 设置为适当的时间值来实现这一点。

总结

Network 框架引入了一些很棒的新类,包括 NWPathMonitor,可用于在 iOS 12+ 上监听设备网络适配器的状态变化。在用户与 captive portal 交互后会将 path 的状态设置为 satisfied,但不会检测后续网络访问的丢失。Connectivity 可以为支持之前 iOS 系统的 App 提供向后兼容性,并通过使用 NWPathMonitor 获取更高的准确性。

优点

  • Apple 官方支持;
  • 无需包含第三方代码 - 只需导入 iOS 12 中的 Network.framework 即可;
  • 在与 captive portal 协商后,报告 NWPath 的状态为 satisfied;

缺点

  • 不能在 iOS 12 之前使用,这意味着如果你需要支持早期版本的 iOS,就会稍显麻烦了;
  • 缺乏详细文档;
  • 在初始连接成功后,不会再检测 captive portals 以及其他 Internet 连接中断的情况;

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

iOS 12+ 中检测网络访问的方法

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

iOS 12+ 中检测网络访问的方法

我最近写了一篇文章,来介绍 iOS 在连接新的 Wi-Fi 网络时,如何在弹出一个 web view 以让用户登录或注册之前,检测 Captive Portals (强制网络门户)。如果你连接过诸如酒店、酒吧或咖啡店等地的公共 Wi-Fi
2022-06-03

javascript中检测网络的方法

这篇文章将为大家详细讲解有关javascript中检测网络的方法,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。javascript检测网络的方法:1、通过navigator去检测网络;2、 使用“wind
2023-06-15

windows10没法自动检测此网络的设置解决方案

windows10没法自动检测此网络的设置怎么办呢,客户最先进到运作,随后右键文件夹中的host选择下面的删掉,接着右键用管理员开启命令提示符,随后输入网络重设的指令,客户就能解决此类问题,下面就是具体的windows10没法自动检测此网络
2023-07-16

解决两种VPN网络访问故障的实现方法

  VPN的英文全称是“Virtual Private Network”,翻译过来就是“虚拟专用网络”。虚拟专用网络大家能够把它理解成是虚拟出来的企业内部专线。虚拟专用网络功能是:在公用网络上建立专用网络,进行加密通讯。现在就跟着小编共同来学习一下:解决两种VPN网络访问
解决两种VPN网络访问故障的实现方法
2024-04-18

Android和IOS的浏览器中检测是否安装某个客户端的方法

我们希望更多的用户用我们的产品,更希望能留住更多的用户。这个时候让用户使用客户端的意义就变得格外重要了。毕竟客户端是实实在在的占据了用户的桌面,每天或多或少都会看到我们的产品。然后,作为手机端的Web产品,用户通过手机浏览器访问到了我们的页
2022-06-06

怎么解决XP中启用Guest无法访问网络的问题

本篇内容主要讲解“怎么解决XP中启用Guest无法访问网络的问题”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么解决XP中启用Guest无法访问网络的问题”吧!好多Windows XP系统启用
2023-06-14

VMWare中Workstation虚拟机访问外网的方法

小编给大家分享一下VMWare中Workstation虚拟机访问外网的方法,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!用的nat模式,以前我一直以为这个是与主机
2023-06-07

Android中访问证书有问题的SSL网页的方法

PC上的浏览器会弹出证书错误的对话框,提示你是否要无视错误继续浏览。实际上在WebView里也可以这样做,以实现加载证书有问题的页面。代码如下:WebView webview = (WebView) findViewById(R.id.we
2022-06-06

Win10无法访问老的NAS设备或linux网络共享的解决方法

比较老的NAS设备或者一些linux系统的SAMBA软件包可能都是使用www.cppcns.com的是SMB1.x协议,Win10支持SMB 3.1.1协议。无法访问的话,就要www.cppcns.com确保系统内SMB1.0协议的安装,下
2023-05-20

云服务器80端口无法访问网络的原因及解决方法

1.网络配置问题如果你的云服务器的80端口无法访问网络,首先需要检查网络配置是否正确。可能的原因包括:1.1防火墙设置防火墙可能会阻止对80端口的访问。你可以检查服务器上的防火墙规则,确保80端口没有被阻止。如果有必要,你可以添加一个允许80端口的规则。1.2路由器设置如果你的云服务器是通过路由器连接到网络的,那么路由
云服务器80端口无法访问网络的原因及解决方法
2023-10-27

Win8.1系统电脑连不上网提示无法自动检测此网络的代理设置的解决方法

运行的Win8.1系统会遇到网络故障,最常见的问题就是连不上网,这不一位用户说Win8.1系统自带的网络诊断会提示”windows无法自动检测此网络的代理设置“,这是怎么回事,且经常出现这个问题,又无法自动修复,小编
2022-06-04

Win7本地连接显示未识别网络 本地连接受限无网络访问的解决方法

win7系统中,通过ADSL PPPOE进行宽带上网,但是一直连接不上去,在连接过程中,右下角的宽带连接就会转啊转,等到提示连接不上的时候,把鼠标放到右下角的图标会提示 “Internet访问 - 本地连接显示未识别&rdquo
2023-06-01

windows安装软件报错无法访问网络位置解决方法是怎样的

本篇文章为大家展示了windows安装软件报错无法访问网络位置解决方法是怎样的,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。开始--运行中输入regedit找到以下路径。按照下面的指示做。HKEY_
2023-06-14

阿里云服务器IP地址无法访问网络的原因及解决方法

在使用阿里云服务器时,有时候会遇到IP地址无法访问网络的问题。本文将分析可能导致该问题的原因,并提供相应的解决方法,帮助用户快速解决这一困扰。1.IP地址配置错误阿里云服务器的IP地址是由系统自动分配的,因此在使用之前需要确保正确配置。如果IP地址配置错误,就无法正常访问网络。常见的错误包括IP地址被其他设备占用
阿里云服务器IP地址无法访问网络的原因及解决方法
2024-01-16

Win7中进行本地连接后显示未识别网络无Internet访问的解决方法

在打开电脑后通常都要先进行网络的连接,但是有时在Win7系统中进行本地连接后却显示未识别网络无Internet访问,怎么连接都连接不上,而且进行疑难解答也没有用,那么遇到这样的情况要怎么办呢?现在我们一起来看看吧! 解决如下:从未识别的网络
2023-06-01

Python网络编程中的常见问题及解决方法

Python网络编程中的常见问题及解决方法引言:在当今互联网时代,网络编程成为了一项重要的技能。Python作为一种功能强大而易学的编程语言,得到了广泛的应用。然而,网络编程中常常会遇到一些问题。本文将介绍一些常见的问题,并给出相应的解决方
2023-10-22

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录