在Swift中使用iOS UIResponder链打开URL

创建iOS应用程序时,我们发现需要一些按钮或UIControls打开URL链接。

这可以通过调用open(_:options:completionHandler 🙂轻松完成。 UIApplication的方法。 通过在iOS 9中添加SFSafariViewController,这为显示链接而无需用户离开应用程序提供了新的可能性。

虽然可以从代码中的任何位置调用UIApplication open(_:options:completionHandler 🙂 ,但仅从 UIViewController可以显示SFSafariViewController

我最近正在开发一个应用程序,该应用程序从JSON对象解析并构建交互式文档。 在构成交互式文档的多个对象中,有一个简单的链接对象。 如果用户点击链接,我们将在不离开应用程序的情况下将内容呈现在SFSafariViewControllerSafariVC )中。

应用程序的层次结构类似于下图:

在根目录下,我们有一个导航控制器,并在看到链接后有多个嵌入。 棘手的部分是将用户交互从链接一直传递到根视图控制器,因此我们可以通过将SafariVC推送到导航堆栈中来呈现SafariVC。

可以使用多种解决方案来解决此问题。 其中之一是将DocumentController分配为Link上TouchUpInside事件的目标,并使用didTapLink(_ link:URL)回调公开Delegate属性。 然后要求DocumentGridController将其父级分配为其子级的委托。

这似乎是一个可行的解决方案,但是它涉及很多约束:

LinkView必须是UIControl

DocumentController需要了解Link

TopicViewController需要遵守协议,

DocumentGridController需要知道其父项并将其分配给其子项。 这变得非常混乱并且难以维护。

最重要的是,如果我们从其他地方提供一个DocumentController ,会发生什么? 我们应该始终记住分配一个委托并实现相应的协议。

如果我们可以使用与iOS触摸处理相同的逻辑怎么办?

目的是在层次结构中传播打开链接的动作。 因此,该层次结构中的每个对象都可以决定是否可以打开URL或将其传递给下一个URL。

如果您不熟悉UIResponder链,我建议您阅读:使用Apple文档中的使用Responders和Responder链来处理事件。

这是一个图表,显示了如果使用UIResponder链进行URL调用,则传播将如何进行。

一旦点击链接,它将传播一个打开URL的调用。 所有中间视图和控制器都将转发它,直到到达将对其进行处理并推送SafariVC的TopicViewController为止

这是协议和实施的片段:

每个符合URLHandler的可以通过响应者链接收URL请求。 UIResponder扩展中的函数broadcastURL将触发传播:

  • 这将确保链尚未结束。 否则,将返回失败
  • 然后它将检查下一个响应者是否无法处理URL。 否则,它将进行传播
  • 如果下一个响应者可以处理URL,它将要求其处理URL。
  • 如果完成不成功,则传播将继续。 否则,URL的传播将停止。

因此,由于我们的LinkView是UIResponder,因此它可以调用broadcastURL来开始传播。 传播将持续到到达符合URLHandler协议的TopicViewController 为止 。 所有中间视图和控制器都将转发呼叫,因为它们不符合URLHandler协议。

TopicViewController的HandleURL方法中,我们可以实例化SafariVC并显示它。

通过具有URLHandler一致性,对象可以决定它是否可以处理URL。 例如,我们的TopicViewController可以检查URL域并决定是在SafariVC中打开它还是继续传播。 在我们的应用中,我们选择使用SFSafariController打开所有链接(Youtube链接除外)。

与触摸事件传播不同,URLHandling可以异步发生。 仅当调用URLHandler方法的完成块时,传播才会继续。 例如,这允许在远程服务器上检查列入白名单的URL。

由于UIApplication也是UIResponder,并且始终位于响应者链的末尾,因此我们可以使用它将所有未处理的URL传播引导到Safari应用程序中。

使用UIResponder链传播URL可以帮助解耦类。 它基于以下事实:如果对象无法处理URL,则应将其传递给下一个对象,依此类推。 使用UIResponder链可确保以应用程序委托结尾的逻辑层次结构。

谢谢阅读!