SwiftUI:WebKit 工具栏按钮没有做任何事情
SwiftUI: WebKit toolbar buttons not doing anything
这是一款使用 SwiftUI 和 WebKit 制作的适用于 macOS 的网络浏览器应用程序。在我的地址工具栏中,我有一些快捷按钮,例如刷新、返回、前进和一个指向 YouTube 的快捷 link 按钮。但是点击其中任何一个都没有任何反应。
内容视图
struct ContentView: View {
@StateObject var webModel = WebStateModel()
@State var text = ""
var body: some View {
//toolbar
HStack{
//Refresh Button
Button(action: {
WebView(webModel: webModel).refresh()
}) {
Image("arrow.left.circle")
}
//Go Forward Button
Button{
WebView(webModel: webModel).goForward()
} label: {
Image("arrow.right.circle")
}
//Youtube button
Button{
WebView(webModel: webModel).youtube()
} label: {
Image("house.circle")
}
}
VStack (spacing: 80) {
TextField("Enter a URL", text: Binding(
get: { text },
set: { text = WebStateModel.stripHttps([=10=]) } ), onCommit: {
webModel.updateUrl(text)
})
WebView(webModel: webModel) //To display the loaded web page
}
}
}
WebView 的视图模型
class WebStateModel: ObservableObject {
@Published var url: URL? = URL(string: "https://www.google.com")
func updateUrl(_ str: String) {
if let theUrl = URL(string: "https://" + WebStateModel.stripHttps(str)) {
url = theUrl
}
}
static func stripHttps(_ str: String) -> String {
var txt = str.trim()
if txt.starts(with: "https://") {
txt = String(txt.dropFirst(8))
}
return txt
}
}
包含工具栏快捷功能的 WebView。
struct WebView: NSViewRepresentable {
@ObservedObject var webModel: WebStateModel
func makeNSView(context: Context) -> WKWebView {
let wkWebview = WKWebView()
if let theUrl = webModel.url {
let request = URLRequest(url: theUrl, cachePolicy: .returnCacheDataElseLoad)
wkWebview.load(request)
}
return wkWebview
}
func updateNSView(_ nsView: WKWebView, context: Context) {
if let theUrl = webModel.url {
let request = URLRequest(url: theUrl, cachePolicy: .returnCacheDataElseLoad)
nsView.load(request)
}
}
func refresh() {
let wkWebview = WKWebView()
wkWebview.reload()
}
func goBack() {
let wkWebview = WKWebView()
guard wkWebview.canGoBack else { return }
wkWebview.goBack()
}
func goForward() {
let wkWebview = WKWebView()
guard wkWebview.canGoForward else { return }
wkWebview.goBack()
}
func youtube() {
let wkWebview = WKWebView()
wkWebview.load(URLRequest(url: (URL(string: "https://www.youtube.com")!)))
}
}
编辑我也试过了
func refresh() {
WKWebView().reload()
}
func goBack() {
guard WKWebView().canGoBack else { return }
WKWebView().goBack()
}
func goForward() {
guard WKWebView().canGoForward else { return }
WKWebView().goForward()
}
func youtube() {
WKWebView().load(URLRequest(url: (URL(string: "https://www.youtube.com")!)))
}
单击工具栏中的任何按钮时,WebView 中没有任何反应。
如前所述,每次调用函数时都会创建一个新对象。
此外,您不应该尝试“return”按钮内的视图。 SwiftUI 是
基于不断变化的状态值。
改为这样做:
import SwiftUI
import WebKit
@main
struct TestApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
class WebStateModel: ObservableObject {
@Published var url: URL? = URL(string: "https://www.google.com")
func updateUrl(_ str: String) {
if let theUrl = URL(string: "https://" + WebStateModel.stripHttps(str)) {
url = theUrl
}
}
static func stripHttps(_ str: String) -> String {
var txt = str.trim()
if txt.starts(with: "https://") {
txt = String(txt.dropFirst(8))
}
return txt
}
}
struct WebView: NSViewRepresentable {
@ObservedObject var webModel: WebStateModel
let wkWebview = WKWebView()
func makeNSView(context: Context) -> WKWebView {
if let theUrl = webModel.url {
let request = URLRequest(url: theUrl, cachePolicy: .returnCacheDataElseLoad)
wkWebview.load(request)
}
return wkWebview
}
func updateNSView(_ nsView: WKWebView, context: Context) {
if let theUrl = webModel.url {
let request = URLRequest(url: theUrl, cachePolicy: .returnCacheDataElseLoad)
nsView.load(request)
}
}
func refresh() {
wkWebview.reload()
}
func goBack() {
guard wkWebview.canGoBack else { return }
wkWebview.goBack()
}
func goForward() {
guard wkWebview.canGoForward else { return }
wkWebview.goForward()
}
func youtube() {
wkWebview.load(URLRequest(url: (URL(string: "https://www.youtube.com")!)))
}
}
extension String {
func trim() -> String {
return self.trimmingCharacters(in: .whitespacesAndNewlines)
}
}
struct ContentView: View {
@StateObject var webModel = WebStateModel()
@State var text = ""
@State var webView: WebView?
var body: some View {
VStack {
//toolbar
HStack{
Button(action: { webView?.refresh() }) {
Image(systemName: "arrow.clockwise.circle")
}
Button(action: { webView?.goBack() }) {
Image(systemName: "arrow.left.circle")
}
Button(action: { webView?.goForward() }) {
Image(systemName: "arrow.right.circle")
}
Button(action: { webView?.youtube() }) {
Image(systemName: "house.circle")
}
}
VStack (spacing: 80) {
TextField("Enter a URL", text: Binding(
get: { text },
set: { text = WebStateModel.stripHttps([=10=]) } ), onCommit: {
webModel.updateUrl(text)
})
webView
}
}
.onAppear {
webView = WebView(webModel: webModel)
}
}
}
这是一款使用 SwiftUI 和 WebKit 制作的适用于 macOS 的网络浏览器应用程序。在我的地址工具栏中,我有一些快捷按钮,例如刷新、返回、前进和一个指向 YouTube 的快捷 link 按钮。但是点击其中任何一个都没有任何反应。
内容视图
struct ContentView: View {
@StateObject var webModel = WebStateModel()
@State var text = ""
var body: some View {
//toolbar
HStack{
//Refresh Button
Button(action: {
WebView(webModel: webModel).refresh()
}) {
Image("arrow.left.circle")
}
//Go Forward Button
Button{
WebView(webModel: webModel).goForward()
} label: {
Image("arrow.right.circle")
}
//Youtube button
Button{
WebView(webModel: webModel).youtube()
} label: {
Image("house.circle")
}
}
VStack (spacing: 80) {
TextField("Enter a URL", text: Binding(
get: { text },
set: { text = WebStateModel.stripHttps([=10=]) } ), onCommit: {
webModel.updateUrl(text)
})
WebView(webModel: webModel) //To display the loaded web page
}
}
}
WebView 的视图模型
class WebStateModel: ObservableObject {
@Published var url: URL? = URL(string: "https://www.google.com")
func updateUrl(_ str: String) {
if let theUrl = URL(string: "https://" + WebStateModel.stripHttps(str)) {
url = theUrl
}
}
static func stripHttps(_ str: String) -> String {
var txt = str.trim()
if txt.starts(with: "https://") {
txt = String(txt.dropFirst(8))
}
return txt
}
}
包含工具栏快捷功能的 WebView。
struct WebView: NSViewRepresentable {
@ObservedObject var webModel: WebStateModel
func makeNSView(context: Context) -> WKWebView {
let wkWebview = WKWebView()
if let theUrl = webModel.url {
let request = URLRequest(url: theUrl, cachePolicy: .returnCacheDataElseLoad)
wkWebview.load(request)
}
return wkWebview
}
func updateNSView(_ nsView: WKWebView, context: Context) {
if let theUrl = webModel.url {
let request = URLRequest(url: theUrl, cachePolicy: .returnCacheDataElseLoad)
nsView.load(request)
}
}
func refresh() {
let wkWebview = WKWebView()
wkWebview.reload()
}
func goBack() {
let wkWebview = WKWebView()
guard wkWebview.canGoBack else { return }
wkWebview.goBack()
}
func goForward() {
let wkWebview = WKWebView()
guard wkWebview.canGoForward else { return }
wkWebview.goBack()
}
func youtube() {
let wkWebview = WKWebView()
wkWebview.load(URLRequest(url: (URL(string: "https://www.youtube.com")!)))
}
}
编辑我也试过了
func refresh() {
WKWebView().reload()
}
func goBack() {
guard WKWebView().canGoBack else { return }
WKWebView().goBack()
}
func goForward() {
guard WKWebView().canGoForward else { return }
WKWebView().goForward()
}
func youtube() {
WKWebView().load(URLRequest(url: (URL(string: "https://www.youtube.com")!)))
}
单击工具栏中的任何按钮时,WebView 中没有任何反应。
如前所述,每次调用函数时都会创建一个新对象。 此外,您不应该尝试“return”按钮内的视图。 SwiftUI 是 基于不断变化的状态值。
改为这样做:
import SwiftUI
import WebKit
@main
struct TestApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
class WebStateModel: ObservableObject {
@Published var url: URL? = URL(string: "https://www.google.com")
func updateUrl(_ str: String) {
if let theUrl = URL(string: "https://" + WebStateModel.stripHttps(str)) {
url = theUrl
}
}
static func stripHttps(_ str: String) -> String {
var txt = str.trim()
if txt.starts(with: "https://") {
txt = String(txt.dropFirst(8))
}
return txt
}
}
struct WebView: NSViewRepresentable {
@ObservedObject var webModel: WebStateModel
let wkWebview = WKWebView()
func makeNSView(context: Context) -> WKWebView {
if let theUrl = webModel.url {
let request = URLRequest(url: theUrl, cachePolicy: .returnCacheDataElseLoad)
wkWebview.load(request)
}
return wkWebview
}
func updateNSView(_ nsView: WKWebView, context: Context) {
if let theUrl = webModel.url {
let request = URLRequest(url: theUrl, cachePolicy: .returnCacheDataElseLoad)
nsView.load(request)
}
}
func refresh() {
wkWebview.reload()
}
func goBack() {
guard wkWebview.canGoBack else { return }
wkWebview.goBack()
}
func goForward() {
guard wkWebview.canGoForward else { return }
wkWebview.goForward()
}
func youtube() {
wkWebview.load(URLRequest(url: (URL(string: "https://www.youtube.com")!)))
}
}
extension String {
func trim() -> String {
return self.trimmingCharacters(in: .whitespacesAndNewlines)
}
}
struct ContentView: View {
@StateObject var webModel = WebStateModel()
@State var text = ""
@State var webView: WebView?
var body: some View {
VStack {
//toolbar
HStack{
Button(action: { webView?.refresh() }) {
Image(systemName: "arrow.clockwise.circle")
}
Button(action: { webView?.goBack() }) {
Image(systemName: "arrow.left.circle")
}
Button(action: { webView?.goForward() }) {
Image(systemName: "arrow.right.circle")
}
Button(action: { webView?.youtube() }) {
Image(systemName: "house.circle")
}
}
VStack (spacing: 80) {
TextField("Enter a URL", text: Binding(
get: { text },
set: { text = WebStateModel.stripHttps([=10=]) } ), onCommit: {
webModel.updateUrl(text)
})
webView
}
}
.onAppear {
webView = WebView(webModel: webModel)
}
}
}