如何防止 WKWebView 对象崩溃?

2024-01-01

Scenario

我正在用 Swift 构建一个 iOS 应用程序。其中一项功能是将实时视频源作为应用程序背景。视频源源自本地网络上的 Raspberry Pi,使用sudo motion。 Motion 已成功在默认端口上托管源8081.

Swift 应用程序有一个WKWebView对象的源指向我的 Raspberry Pi 的运动端口。

疑似问题

端口网页8081不断刷新以从相机加载最新的帧。

Problem

运行应用程序时,提要成功连接并加载第一帧,偶尔会加载第二帧,但随后会中断。

有几次我在终端中收到以下错误:[ProcessSuspension] 0x282022a80 - ProcessAssertion() Unable to acquire assertion for process with PID 0让我相信这是一个与网页不断刷新性质相关的内存管理问题。

当前配置

目前,我对 .load() 的调用WKWebView对象位于ViewController.swift > override func viewDidLoad().

拟议决议

我是否需要构建某种形式的循环结构,在其中加载帧,暂停执行,然后调用WKWebView几秒钟后重新加载新帧。

我对 Swift 很陌生,所以非常感谢您对我的问题格式的耐心。


WkWebView 和动作加载在 iOS 11 版本的 Xcode 9 中工作,但似乎不再在 iOS 12 中工作。你是对的,webkit 在第二张图像上崩溃了​​。

由于您是 Swift 新手,我建议您阅读有关代表的链接,因为我提供的这个解决方案对您来说更有意义。快速代表 https://medium.com/@jamesrochabrun/implementing-delegates-in-swift-step-by-step-d3211cbac3ef总之,“委托是一种设计模式,允许一个对象在特定事件发生时向另一个对象发送消息。”

通过这个解决方案/黑客,我们将使用几个 WKNavigationDelegates 来通知我们 WkWebView 何时执行特定任务,并将我们的解决方案注入到问题中。您可以在此处找到 WKWebKit 拥有的所有委托WK导航代表 https://developer.apple.com/documentation/webkit/wknavigationdelegate.

下面的代码可以在一个全新的iOS项目中使用并替换ViewController.swift中的代码。它不需要接口生成器或 IBOutlet 连接。它将在视图上创建单个 Web 视图并指向地址 192.168.2.75:6789。我添加了内联注释来尝试解释代码的作用。

  1. 我们在decidePolicyFor navigationResponse 委托中从运动中加载HTTP 响应两次,并使用计数器进行跟踪。我留下了一些打印声明,以便您可以看到响应是什么。第一个是标题,第二个是图像信息。
  2. 当我们的计数器达到 3 个项目(即第二张图像)时,我们将强制 wkWebView 取消decidePolicyFor navigationResponse 委托中的所有导航(即停止加载)。请参阅带有 DecisionHandler(.cancel) 的行。这就是阻止崩溃的原因。
  3. 这导致我们接收来自 wkwebview 委托 WebView didFail 导航的回调。此时我们要再次加载 Motion/pi url 并再次开始加载过程。
  4. 然后我们必须重置计数器,以便我们可以重复此过程,直到其他人提出更好的解决方案。

    import UIKit
    import WebKit
    
    class ViewController: UIViewController, WKNavigationDelegate  {
    
        // Memeber variables
        var m_responseCount = 0; /* Counter to keep track of how many loads the webview has done.
                        this is a complete hack to get around the webkit crashing on
                        the second image load */
        let m_urlRequest = URLRequest(url: URL(string: "http://192.168.2.75:6789")!) //Enter your pi ip:motionPort
        var m_webView:WKWebView!
    
        override func viewDidLoad() {
            super.viewDidLoad()
            m_webView = WKWebView(frame: self.view.frame)  // Create our webview the same size as the viewcontroller
            m_webView.navigationDelegate = self            // Subscribe to the webview navigation delegate
        }
    
        override func viewDidAppear(_ animated: Bool) {
            m_webView.load(m_urlRequest)                    // Load our first request
            self.view.addSubview(m_webView)                 // Add our webview to the view controller view so we can see it
        }
    
        // MARK: - WKNavigation Delegates
        func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
            print("decidePolicyFor navigationAction")
            print(navigationAction.request) //This is the request to connect to the motion/pi server http::/192.168.2.75:6789
            decisionHandler(.allow)
        }
    
        func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
            print("decidePolicyFor navigationResponse")
            print(navigationResponse.response) // This is HTML from the motion/rpi
    
        /* We only want to load the html header and the first image
           Loading the second image is causing the crash
             m_responseCount = 0 - Header
             m_responseCount = 1 - First Image
             m_responseCount >= 2 - Second Image
        */
            if(m_responseCount < 2)
            {
                decisionHandler(.allow)
            }
            else{
                decisionHandler(.cancel) // This leads to webView::didFail Navigation Delegate to be called
            }
    
            m_responseCount += 1;  // Incriment our counter
    
        }
    
        func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
        /*
         We have forced this failure in webView decidePolicyFor navigationResponse
         by setting decisionHandler(.cancel)
         */
            print("didFail navigation")
    
            m_webView.load(m_urlRequest) //Lets load our webview again
            m_responseCount = 0     /*  We need to reset our counter so we can load the next header and image again
                                    repeating the process forever
                                */
        }
    
        func webViewWebContentProcessDidTerminate(_ webView: WKWebView) {
        // If you find your wkwebview is still crashing break here for
        // a stack trace
            print("webViewWebContentProcessDidTerminate")
    
        }
    }
    

注意:由于 Motion/pi 服务器响应是 http 而不是 https,您还需要将以下内容添加到 info.plist 文件中

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoadsInWebContent</key>
    <true/>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

我鼓励您使用这个基本示例并对其进行修改以满足您的应用程序要求。我还鼓励您发布您自己的任何发现,因为我使用与您完全相同的硬件遇到了完全相同的问题,这不仅仅是解决方案,更是一种黑客攻击。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何防止 WKWebView 对象崩溃? 的相关文章

随机推荐

  • 如何找出真实屏幕刷新率(不是四舍五入的数字)

    根据微软的这篇文章 http support microsoft com kb 2006076 en us用户设置的屏幕刷新率可以 并且大部分是 小数 用户设置为 59Hz 但屏幕按照屏幕显示 60Hz 运行 但实际上是 59 94Hz 我
  • 我可以放慢 Django 的速度吗

    确实很简单的问题 manage py runserver 我可以慢下来吗localhost 8000在我的开发机器上 以便我可以模拟文件上传并处理 ajax 上传的外观和感觉 取决于你想模拟的地方 这样你就可以简单地睡觉吗 from tim
  • Android 异步任务一个接一个

    我有一个现有的代码 其中有一个用于某些请求响应的异步任务 在执行后方法中 它将解析的数据设置到某个数据库中 现在我需要修改此代码 以便在应用程序启动时 数据被一一下载 即我需要执行任务 A 然后在其完全完成后 即使数据已设置 我需要启动任务
  • int.TryParse = null 如果不是数字?

    如果无法将字符串解析为 int 是否有某种方法返回 null with public string categoryID int TryParse categoryID out categoryID 获取 无法从 out string 转换
  • for循环到底是如何工作的[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 这是一个非常简单的 for 循环 for int i 0 i lt 100 i System out println i 我知道它主要
  • WP All Import Pro:Polylang 兼容性

    我正在尝试使用 WP All Import 的专业版将数据从 Excel 工作表导入到 WordPress 中 我们使用 Polylang 来支持多语言 我想知道如何管理将内容导入正确的语言版本 我发现有一个隐藏的分类 语言 我可以手动将其
  • iPhone:协处理器偏移超出范围

    我在 xcode 和 iphone 上遇到了一个奇怪的编译问题 我的游戏即将完成 但现在我突然遇到这个编译错误 standard input 6108 co processor offset out of range gcc 4 2 fai
  • 使用 iOS 11 中增加的导航栏标题

    iOS 11 Beta 1 几乎所有系统应用程序都使用了增加的导航栏标题 它开始在 iOS 10 和音乐应用程序中这样做 我想知道 Apple 是否在 iOS 11 中为此提供了公共 API 或者目前是否会保持私有状态 行为是标题的字体大小
  • 创建带有限制的 XSD 可选小数元素

    我已经成功地使用以下方法创建了一个可选的小数元素
  • HandlerThread 中的 NullPointerException

    这个错误让我困惑了几个小时 我正在得到空指针异常 问题是这个错误不一致 当我启动应用程序时会发生这种情况 但只是偶尔 所以我不确定是什么原因造成的 对于错误日志中的冗长问题 我深表歉意 但我找不到其他询问方式 错误日志如下 FATAL EX
  • 查找某个表的数据来源-ORACLE

    这可能是一个微不足道的问题 但是 由于我正在处理很久以前由其他人创建的数据库 没有包含适当的文档或注释 所以我遇到了一个关键问题 我需要知道数据如何插入到某个表中 有没有脚本或者其他方法可以识别数据源 换句话说 我需要知道数据是否是通过某些
  • 仅允许视频嵌入代码 (Rails)

    我想知道是否有人知道一种方法 只允许将来自 youtube vimeo blip tv 等的代码嵌入到表单字段中 我的网站上有一个表单 允许用户嵌入视频 但我只希望他们添加嵌入代码 html 而不添加任何其他危险的内容 例如 JS 或其他
  • 使用 node-inspector 调试 karma-jasmine 测试

    几乎同样的问题使用 node inspector 调试 jasmine node 测试 https stackoverflow com questions 6162920 debugging jasmine node tests with
  • Xcode 11 beta 无法将应用程序上传到 TestFlight

    我正在尝试将我的应用程序分发到 TestFlight 目前我的应用程序需要 iOS 13 以及 NFC 访问 在 iOS 13 结束测试版之前 我不打算发布我的应用程序 但我希望我的 QA 团队能够对其进行测试 我可以从 Xcode 11
  • 多个图表延迟问题,SVG 还是 HTML5 Canvas?

    我正在寻找使用 Javascript 构建动态且交互式的多个图表 在此练习中涉及同时移动 平移多个图表 我已经使用 SVG 和各种图表库实现了这个练习 然而 我发现当我开始拥有超过 12 个图表时 平移渲染变得缓慢 Highcharts 库
  • 在 C# 中,Array.ToArray() 是否执行深度复制?

    这应该是一个非常基本的问题 但我在找到明确的答案时遇到了一些困难 当你有一个值数组并使用 ToArray 方法 它创建数组的深副本还是浅副本 No 您可以通过编写一个小程序进行测试来轻松验证这一点
  • PHP 警告: include(/var/www/html/....../lib/Cake/Error/ErrorHandler.php): 无法打开流错误

    我在尝试加载网页时遇到此错误 错误消息中显示的路径是 PHP 警告 包括 var www html test com www products abc lib Cake Error ErrorHandler php 无法打开流 它无法找到
  • Angular 6 Universal 不等待解析器完成

    我刚刚安装了 Angular Universal 启动套件版本6并在其中创建了我的组件 该组件应在加载时通 过 API 获取用户信息并将其显示以供查看 问题是 API 结果显示在浏览器中 但未显示在 查看源代码 什么叫普惠如此 My get
  • 变量神秘消失? AWS 代码构建

    接下来是我的 buildspec yml build commands IMAGE TAG cat package json grep version head 1 awk F print 2 sed s g echo IMAGE TAG
  • 如何防止 WKWebView 对象崩溃?

    Scenario 我正在用 Swift 构建一个 iOS 应用程序 其中一项功能是将实时视频源作为应用程序背景 视频源源自本地网络上的 Raspberry Pi 使用sudo motion Motion 已成功在默认端口上托管源8081 S