我正在尝试创建一个显示该网站收件箱的菜单栏应用程序。我想做一个简单的功能,用该项目的网址打开一个小的弹出窗口(不打开野生动物园)。收件箱项目看起来像这样
struct InboxItem: View {
@State var MesgSite: String = "https://duckduckgo.com"
@State private var showSafari = false
var body: some View {
VStack(alignment: .leading) {
Text("some text")
.background(SelectColor.opacity(0.5))
.onLongPressGesture {
//show preview of the MesgSite here
self.SelectColor = .blue
self.showSafari.toggle()
}.popover(isPresented: self.$showSafari) {
SafariPreview()
}
}
}
struct SafariPreview: View {
var body: some View {
VStack {
Text("Display the webpage here")
.padding()
}.frame(maxWidth: 533, maxHeight: 300)
}
}
我想,当长按该项目时,它应该像在macOS上的默认邮件应用程序中那样预览关联的网页,如下所示:
现在弹出窗口工作了
我曾尝试添加一个wkwebview
,以及一个SafariView
在一个NSViewRepresentable
,但是我有(间相似)使用代码从下面的错误消息这个SO交
Use of undeclared type 'UIViewRepresentable'
TIA!
该项目的最基本版本可以在github上找到
更加关注这个问题
我也曾想出一个解决方案。由于我在该网上都找不到任何文档,因此我将通过反复试验给出我找到的解决方案。
首先,事实证明UI...
,它在macOS上的对应版本名为NS...
。因此UIViewRepresentable
将NSViewRepresentable
在macOS上。接下来,我发现了这样的问题,其中有一个WKWebview
关于macOS的示例。通过将该代码与另一个SO问题上的答案结合起来,我还可以检测到URL变化,并且知道何时完成视图加载。
这导致了以下代码。为了清楚起见,我建议将其放在另一个文件中,例如WebView.swift
:
首先,导入所需的软件包:
import SwiftUI
import WebKit
import Combine
然后创建一个模型,其中包含您希望能够在SwiftUI视图中访问的数据:
class WebViewModel: ObservableObject {
@Published var link: String
@Published var didFinishLoading: Bool = false
@Published var pageTitle: String
init (link: String) {
self.link = link
self.pageTitle = ""
}
}
最后,创建struct
with NSViewRepresentable
,将其作为类似HostingViewController的代码,WebView()
如下所示:
struct SwiftUIWebView: NSViewRepresentable {
public typealias NSViewType = WKWebView
@ObservedObject var viewModel: WebViewModel
private let webView: WKWebView = WKWebView()
public func makeNSView(context: NSViewRepresentableContext<SwiftUIWebView>) -> WKWebView {
webView.navigationDelegate = context.coordinator
webView.uiDelegate = context.coordinator as? WKUIDelegate
webView.load(URLRequest(url: URL(string: viewModel.link)!))
return webView
}
public func updateNSView(_ nsView: WKWebView, context: NSViewRepresentableContext<SwiftUIWebView>) { }
public func makeCoordinator() -> Coordinator {
return Coordinator(viewModel)
}
class Coordinator: NSObject, WKNavigationDelegate {
private var viewModel: WebViewModel
init(_ viewModel: WebViewModel) {
//Initialise the WebViewModel
self.viewModel = viewModel
}
public func webView(_: WKWebView, didFail: WKNavigation!, withError: Error) { }
public func webView(_: WKWebView, didFailProvisionalNavigation: WKNavigation!, withError: Error) { }
//After the webpage is loaded, assign the data in WebViewModel class
public func webView(_ web: WKWebView, didFinish: WKNavigation!) {
self.viewModel.pageTitle = web.title!
self.viewModel.link = web.url?.absoluteString as! String
self.viewModel.didFinishLoading = true
}
public func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) { }
public func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
decisionHandler(.allow)
}
}
}
此代码可以按如下方式使用:
struct ContentView: View {
var body: some View {
//Pass the url to the SafariWebView struct.
SafariWebView(mesgURL: "https://stackoverflow.com/")
}
}
struct SafariWebView: View {
@ObservedObject var model: WebViewModel
init(mesgURL: String) {
//Assign the url to the model and initialise the model
self.model = WebViewModel(link: mesgURL)
}
var body: some View {
//Create the WebView with the model
SwiftUIWebView(viewModel: model)
}
}
因此,现在我们有了这些知识,重新创建方便的野生动物园预览相对容易。
为此,请确保将添加@State private var showSafari = false
(当您要显示预览时会切换)到将调用预览的视图中。
同时添加.popover(isPresented: self.$showSafari) { ...
以显示预览
struct ContentView: View {
@State private var showSafari = false
var body: some View {
VStack(alignment: .leading) {
Text("Press me to get a preview")
.padding()
}
.onLongPressGesture {
//Toggle to showSafari preview
self.showSafari.toggle()
}//if showSafari is true, create a popover
.popover(isPresented: self.$showSafari) {
//The view inside the popover is made of the SafariPreview
SafariPreview(mesgURL: "https://duckduckgo.com/")
}
}
}
现在SafariPreview struct
将如下所示:
struct SafariPreview: View {
@ObservedObject var model: WebViewModel
init(mesgURL: String) {
self.model = WebViewModel(link: mesgURL)
}
var body: some View {
//Create a VStack that contains the buttons in a preview as well a the webpage itself
VStack {
HStack(alignment: .center) {
Spacer()
Spacer()
//The title of the webpage
Text(self.model.didFinishLoading ? self.model.pageTitle : "")
Spacer()
//The "Open with Safari" button on the top right side of the preview
Button(action: {
if let url = URL(string: self.model.link) {
NSWorkspace.shared.open(url)
}
}) {
Text("Open with Safari")
}
}
//The webpage itself
SwiftUIWebView(viewModel: model)
}.frame(width: 800, height: 450, alignment: .bottom)
.padding(5.0)
}
}
结果看起来像这样:
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句