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