我正在使用从一篇很棒的文章 here 中找到的代码演示了如何在 SwiftUI 中使用 LinkPresentation 框架。
但是我遇到了一个小问题,我找不到解决方案 - 链接预览加载其元数据,但完全加载后不会刷新 View ,除非我执行一些强制 View 刷新的操作,例如旋转 View 电话。
它们加载的内容如下:
旋转后如下所示:
我希望 View 在元数据加载后完全刷新。我觉得我可能需要在某个地方添加一些绑定(bind),但我不知道在哪里。有人能帮忙吗?
这是 UIViewRepresentable
import SwiftUI
import LinkPresentation
struct URLPreview : UIViewRepresentable {
var previewURL:URL
func makeUIView(context: Context) -> LPLinkView {
LPLinkView(url: previewURL)
}
func updateUIView(_ view: LPLinkView, context: Context) {
// New instance for each update
let provider = LPMetadataProvider()
provider.startFetchingMetadata(for: previewURL) { (metadata, error) in
if let md = metadata {
DispatchQueue.main.async {
view.metadata = md
view.sizeToFit()
}
}
}
}
}
其名称如下:
struct Content: View {
var body: some View {
URLPreview(previewURL: URL(string: "www.apple.com")!)
}
}
最佳答案
触发重画正是您所需要的。不喜欢这个,但您可以尝试绑定(bind)状态 CGSize 并将框架设置为宽度/高度。
struct URLPreview : UIViewRepresentable {
var previewURL:URL
//Add binding
@Binding var metaSize: CGSize
func makeUIView(context: Context) -> LPLinkView {
LPLinkView(url: previewURL)
}
func updateUIView(_ view: LPLinkView, context: Context) {
// New instance for each update
let provider = LPMetadataProvider()
provider.startFetchingMetadata(for: previewURL) { (metadata, error) in
if let md = metadata {
DispatchQueue.main.async {
view.metadata = md
view.sizeToFit()
//Set binding after resize
self.metaSize = view.frame.size
}
}
}
}
}
struct ContentView: View {
//can default original state
@State var metaSize: CGSize = CGSize()
var body: some View {
URLPreview(previewURL: URL(string: "www.apple.com")!, metaSize: $metaSize)
.frame(width: metaSize.width, height: metaSize.height)
}
}
更新
NSPratik 是对的,该解决方案对于列表来说并不真正可行。所以修改后的解决方案实际上只是使用一个简单的 Bool State 来切换列表生成的 View:
struct ContentView: View {
//can default original state
@State var togglePreview = false
let urls: [String] = ["https://medium.com","https://apple.com","https://yahoo.com","https://stackoverflow.com"]
var body: some View {
List(urls, id: \.self) { url in
URLPreview(previewURL: URL(string: url)!, togglePreview: self.$togglePreview)
.aspectRatio(contentMode: .fit)
.padding()
}
}
}
struct URLPreview : UIViewRepresentable {
var previewURL:URL
//Add binding
@Binding var togglePreview: Bool
func makeUIView(context: Context) -> LPLinkView {
let view = LPLinkView(url: previewURL)
let provider = LPMetadataProvider()
provider.startFetchingMetadata(for: previewURL) { (metadata, error) in
if let md = metadata {
DispatchQueue.main.async {
view.metadata = md
view.sizeToFit()
self.togglePreview.toggle()
}
}
}
return view
}
func updateUIView(_ uiView: LPLinkView, context: UIViewRepresentableContext<URLPreview>) {
}
}
我们只需使用 togglePreview
作为触发器,将其传递给 UIView 中的 Binding var,然后设置我们的列表。即使这触发了列表中的所有 View ,也不会出现任何动画来反射(reflect)完全加载的 LinkView 的大小调整。
关于swift - LinkPresentation View 未在 SwiftUI 中完全加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58047780/