我正在寻找为 SwiftUI WebView 实现“拉动刷新”机制的最佳方法。
这是我能写的最接近的解决方案,但是刷新过程并未结束(事件指示器存在并且没有其他事情发生) 我从这篇文章中获取的这两个扩展 https://stackoverflow.com/a/36256504
import SwiftUI
import WebKit
struct WebView: UIViewRepresentable {
let webView: WKWebView
init() {
webView = WKWebView(frame: .zero)
webView.load(URLRequest(url: URL(string: "https://cnn.com")!))
webView.setPullToRefresh(type: .embed)
}
func makeUIView(context: Context) -> WKWebView {
webView
}
func updateUIView(_ uiView: WKWebView, context: Context) {}
}
extension WKWebView {
var refreshControl: UIRefreshControl? { (scrollView.getAllSubviews() as [UIRefreshControl]).first }
enum PullToRefreshType {
case none
case embed
}
func setPullToRefresh(type: PullToRefreshType) {
(scrollView.getAllSubviews() as [UIRefreshControl]).forEach { $0.removeFromSuperview() }
switch type {
case .none: break
case .embed: _setPullToRefresh(target: self, selector: #selector(webViewPullToRefreshHandler(source:)))
}
}
private func _setPullToRefresh(target: Any, selector: Selector) {
let refreshControl = UIRefreshControl()
refreshControl.addTarget(target, action: selector, for: .valueChanged)
scrollView.addSubview(refreshControl)
}
@objc func webViewPullToRefreshHandler(source: UIRefreshControl) {
guard let url = self.url else { source.endRefreshing(); return }
load(URLRequest(url: url))
}
}
extension UIView {
class func getAllSubviews<T: UIView>(from parenView: UIView) -> [T] {
return parenView.subviews.flatMap { subView -> [T] in
var result = getAllSubviews(from: subView) as [T]
if let view = subView as? T { result.append(view) }
return result
}
}
func getAllSubviews<T: UIView>() -> [T] { return UIView.getAllSubviews(from: self) as [T] }
}
最佳答案
好的,这是我解决这个问题的方法。 在 iPhone 14 Pro、iOS 15 和 16
上检查swift 5
import SwiftUI
import WebKit
struct HomeView: UIViewRepresentable {
var webView = WebView()
func makeUIView(context: Context) -> WKWebView {
webView.webView
}
func updateUIView(_ uiView: WKWebView, context: Context) {}
}
class WebView: NSObject {
var webView: WKWebView!
override init() {
super.init()
webView = WKWebView(frame: .zero)
webView.load(URLRequest(url: URL(string: "https://cnn.com")!))
webView.setPullToRefresh()
webView.navigationDelegate = self
}
}
extension WebView: WKNavigationDelegate {
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
webView.refreshControl?.endRefreshing()
}
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
webView.refreshControl?.endRefreshing()
}
func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
webView.refreshControl?.endRefreshing()
}
}
extension WKWebView {
var refreshControl: UIRefreshControl? {
(scrollView.getAllSubviews() as [UIRefreshControl]).first
}
func setPullToRefresh() {
(scrollView.getAllSubviews() as [UIRefreshControl]).forEach {
$0.removeFromSuperview()
}
let refreshControl = UIRefreshControl()
refreshControl.addTarget(self, action: #selector(webViewPullToRefreshHandler(source:)), for: .valueChanged)
scrollView.addSubview(refreshControl)
}
@objc func webViewPullToRefreshHandler(source: UIRefreshControl) {
guard let url = self.url else {
source.endRefreshing()
return
}
load(URLRequest(url: url))
}
}
extension UIView {
class func getAllSubviews<T: UIView>(from parentView: UIView) -> [T] {
return parentView.subviews.flatMap { subView -> [T] in
var result = getAllSubviews(from: subView) as [T]
if let view = subView as? T {
result.append(view)
}
return result
}
}
func getAllSubviews<T: UIView>() -> [T] {
return UIView.getAllSubviews(from: self) as [T]
}
}
关于ios - 在 SwiftUI WebView 中拉动刷新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74295405/