使用可达性有啥好处?

Posted

技术标签:

【中文标题】使用可达性有啥好处?【英文标题】:What is the advantage of using Reachability?使用可达性有什么好处? 【发布时间】:2011-08-24 15:43:27 【问题描述】:

与下面的代码相比,使用 Reachability 有什么优势?我觉得 Reachability 的代码量很大,但如果它在任何方面更好,那么我会改用它。

NSString *connectionString = [[NSString alloc] initWithContentsOfURL:[NSURL URLWithString:@"http://www.google.com"]];

if ([connectionString length] == 0) 

    //No connection


现在承认,如果 Google 出现故障,那么这将行不通。但从字面上看,这种情况发生的可能性不大。你怎么看?谢谢!

【问题讨论】:

Reachabity 也使用主机来测试互联网可用性,我相信 google.com 被广泛用作基准。 【参考方案1】:

这实际上是一个很好的问题 - 太好了,以至于我在公司招聘时在 ios 开发人员面试中实际使用了它:

为什么 Apple 的可达性示例长达数百行,而您可以只使用一行来检查 URL 是否响应?

首先,网络可达性实际上非常非常复杂。它不仅仅是简单地测试一个 URL。考虑以下示例:

用户在使用 3G,但已用完数据限额,所以每个 请求重定向到运营商的网站。

用户连接到公共 WiFi 网络,需要 身份验证/登录,因此请求重定向到登录页面

最后一个例子非常普遍 - 它一直在发生。但是,如果您使用initWithContentsOfURL,您的应用程序会认为您有连接,而实际上您没有:您只会返回网络将您重定向到的页面的内容。

这就是为什么 Apple 的代码比您最初想象的要复杂的原因之一。您不应该只是问“我可以到达这个 URL”,而是 “从这个 URL 返回的数据是我期望的数据”。

但这只是冰山一角。除此之外,可达性还有很多作用——例如,我可能有一个需要下载大量信息的应用程序,比如 50MB 的信息。如果用户在未经他们同意的情况下使用 3G 连接,那么简单地下载 50MB 数据将是一个坏主意——尤其是在他们正在漫游或使用受限数据计划的情况下。因此,Reachability 还会告诉您用户使用的连接类型:EDGE、3G、WiFi 等(*注意:请参阅下面的注释,这可能不是最好的建议)。

Reachability 中的ReadMe.txt 将告诉您更多关于代码可以做什么和不能做什么的信息。

不幸的是,网上有太多人没有意识到initWithContentsOfURL 将返回有效响应但用户 连接的许多日常场景。 [像这样的博客文章][1] 在 Google 中被编入索引,人们认为这是可以接受的替代品:事实并非如此!

我在招聘时问这个问题的原因之一是它可以表明开发人员不仅仅是在框内思考 - 就像您和许多其他开发人员一样,当我看到可达性示例代码时,我的第一反应是“哇,这似乎对于非常简单的事情来说太复杂了”。但希望这个答案能在某种程度上说服你。


编辑:一定要注意下面的 Steven 的 cmets。他提出了一些我的回答没有考虑到的观点(即 MiFi 热点),并提出了一个有效的案例,即可达性不一定是编码天堂的顶峰。在许多情况下,开发人员会通过自己的改进等来修改可达性。

【讨论】:

这也是正确的,但在判断这个问题的答案时我会谨慎行事。也有很多理由不使用可达性:也就是说,它是一个庞大的混乱。是的,这种混乱是有目的的,但一个有效的问题是目的是否值得。其中最有价值的部分是在连接状态更改时收到通知,以便您可以重试连接,结果证明这只是几行代码。 可达性应该永远被用作预检检查,而只是为了解释为什么某些东西不工作。 (我是作为一名开发人员说的,他有一个使用可达性作为预检检查的应用程序。这是一个坏主意。) 事实上,补充最后一条评论:在某些情况下,可达性会报告网络连接不可达。但是,如果您尝试连接而不是询问可达性,它将是可达的。 (并且,在连接后,Reachability 会告诉您它可用。) 另外,这个答案中关于依靠可达性来确定网络连接的类型的建议是非常糟糕的建议。可达性不处理强制网络。如果您在带 wifi 的巴士上,但巴士通过 3G 提供 wifi 怎么办?你需要测量。观看 WWDC 2011 会议 200。 在 Ipad 5.1.1 上,Apple 的可达性代码正确地报告不可用,但在您重新获得网络访问权时无法报告可用。看来,如果您打算使用它,它是为了确定您的 iPad 的服务器是否关闭或网络是否关闭,访问失败之后。【参考方案2】:

Reachability 的最大问题不是它是糟糕的代码,或者它是糟糕的代码使用。现在它实际上是相当不错的代码。但它很容易被误解和误用于非预期目的。

以下是使用可达性的一些指南:

是的,使用可达性。也许最明显的一点是:可达性是让您的应用感觉更自然的重要资产。 永远不要将 Reachability 用作预检。 仅仅因为 Reachability 报告网络当前不可用并不意味着它不会变为可用如果您尝试使用它。你没有发送的网络请求可能正是唤醒 iOS 网络的东西。 编辑:实际上,我可能应该稍微缓和一下。将 unrequested 操作推迟一小段时间可能是有意义的。在其他条件相同的情况下,最好连续进行所有网络连接,而不是反复打开和关闭硬件。如果可能的话要爆发!但是您应该永远不要阻止用户根据可达性做某事。 使用 Reachability 来帮助诊断失败的原因。 尝试建立网络后,Reachability 会告诉您网络不可用。这是可用于构建良好错误消息的宝贵信息,并且可能比 API 返回的确切错误代码更重要。 允许用户手动重试。用户可能知道网络应该从这个位置工作。不要依赖 iOS 来发现网络现在可用并且 Reachability 会通知您。同样,尝试可能是使它可用的东西。 使用 Reachability 的通知自动重试。当 Reachability 告诉您网络可用时,这是因为它可用。在您完成尝试之前,它可能会再次出现故障,并且它可能是一个强制网络,但现在是再次尝试您的请求的好时机。

您可以在 Mobile Safari 中看到此行为。如果页面加载失败,您可以重试,无论 iPhone 是否认为您有连接。但是,如果网络可用并且 Mobile Safari 发出通知,它将自动重试。感觉很自然。

记住这些准则:

    移动网络并不简单。 确定网络连接是否成功的唯一可靠方法是尝试它并查看它是否确实成功。 确定网络连接是否实际成功并非易事。

在 WWDC 2011 上有几场关于移动网络的会议值得一看。 (2010 年有几个也解决了这个问题,我相信 WWDC 2012 也会有几个。这不是一个简单的问题,它不会消失。)

另外:initWithContentsOfURL 是同步的。不要在 iOS 上使用同步网络。如果花费了意外的长时间,您的应用将被 iOS 看门狗退出。

【讨论】:

【参考方案3】:

可达性的一个优点是它可以在连接状态发生变化时向您发送通知。通过这种方式,您可以通知您的用户某些功能可能会受到限制。

【讨论】:

【参考方案4】:

所有优点。我将补充:考虑使用 NSURLConnection。它有一个委托协议,可以通知您在尝试建立连接时发生的所有相关事件/事件。它为您提供了比简单的 initWithCintentsOfURL 方法更多的控制权,并允许异步处理。 但是如果你从许多类中使用它,那么多次实现所有的委托方法可能会变得很麻烦。我将它封装在一个只有两个委托方法的自定义类中:didFaildidFinish,并在我的所有代码中重用该类。

【讨论】:

【参考方案5】:

除了@lxt 的出色回答之外,使用 Reachibility 的另一个很好的理由是,如果您没有在应用程序内部执行尽职调查以考虑连接方案,那么您的应用程序将被拒绝。 Apple 会在有连接和没有连接的情况下测试你的应用程序,如果它在其中任何一种情况下都失败了,你的应用程序甚至都不会被查看。

我完全同意 lxt 的回答。它为您提供了更多关于连接的详细信息,而不仅仅是“我可以连接到某个网站”。好问题。

【讨论】:

以上是关于使用可达性有啥好处?的主要内容,如果未能解决你的问题,请参考以下文章

在 Swift 中使用可达性类

在运行方法之前使用可达性检查连接

可达性与 UIDevice-可达性

使用多个视图控制器时的可达性检查

对象可达性状态流转分析引用队列使用和诊断 JVM 引用情况知识讲解

使用可达性的语义问题