ali*_*ego 11 xcode ios swiftui
我正在尝试在 SwiftUI 列表中显示丰富的链接,无论我尝试什么,我似乎都无法更改屏幕上链接视图(UIViewRepresentable)的大小。
特定链接是否有最小尺寸?我怎样才能得到它。添加 .aspectRatio 和 Clipped() 将尊重大小,但链接被严重剪裁。不知道为什么链接不会调整宽高比以适合视图。
以下部分代码源自以下教程: https ://www.appcoda.com/linkpresentation-framework/
我使用以下 UIViewRepresentable 作为 LinkView:
import SwiftUI
import LinkPresentation
struct LinkViewRepresentable: UIViewRepresentable {
typealias UIViewType = LPLinkView
var metadata: LPLinkMetadata?
func makeUIView(context: Context) -> LPLinkView {
guard let metadata = metadata else { return LPLinkView() }
let linkView = LPLinkView(metadata: metadata)
return linkView
}
func updateUIView(_ uiView: LPLinkView, context: Context) {
}
}
Run Code Online (Sandbox Code Playgroud)
我对 List 的看法是:
import SwiftUI
import LinkPresentation
struct ContentView: View {
@ObservedObject var linksViewModel = LinksViewModel()
var links: [(String, String)] = [("https://www.apple.com", "1"), ("https://www.stackoverflow.com", "2")]
var body: some View {
ScrollView(.vertical) {
LazyVStack {
ForEach(links, id: \.self.1) { link in
VStack {
Text(link.0)
.onAppear {
linksViewModel.getLinkMetadata(link: link)
}
if let richLink = linksViewModel.links.first(where: { $0.id == link.1 }) {
if let metadata = richLink.metadata {
if metadata.url != nil {
LinkViewRepresentable(metadata: metadata)
.frame(width: 200) // setting frame dimensions here has no effect
}
}
}
}
}
}
.padding()
}
}
}
Run Code Online (Sandbox Code Playgroud)
设置视图的框架或 contentMode(.fit) 或填充或我尝试过的任何其他内容都不会更改 LinkViewRepresentable 的框架的大小。我已经在更新的可代表中尝试了 sizeToFit ,但没有成功。是否可以在这里控制可表示视图的大小?
以下是其他文件:
import Foundation
import LinkPresentation
class LinksViewModel: ObservableObject {
@Published var links = [Link]()
init() {
loadLinks()
}
func createLink(with metadata: LPLinkMetadata, id: String) {
let link = Link()
link.id = id
link.metadata = metadata
links.append(link)
saveLinks()
}
fileprivate func saveLinks() {
do {
let data = try NSKeyedArchiver.archivedData(withRootObject: links, requiringSecureCoding: true)
guard let docDirURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
try data.write(to: docDirURL.appendingPathComponent("links"))
print(docDirURL.appendingPathComponent("links"))
} catch {
print(error.localizedDescription)
}
}
fileprivate func loadLinks() {
guard let docDirURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
let linksURL = docDirURL.appendingPathComponent("links")
if FileManager.default.fileExists(atPath: linksURL.path) {
do {
let data = try Data(contentsOf: linksURL)
guard let unarchived = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as? [Link] else { return }
links = unarchived
} catch {
print(error.localizedDescription)
}
}
}
func fetchMetadata(for link: String, completion: @escaping (Result<LPLinkMetadata, Error>) -> Void) {
guard let uRL = URL(string: link) else { return }
let metadataProvider = LPMetadataProvider()
metadataProvider.startFetchingMetadata(for: uRL) { (metadata, error) in
if let error = error {
print(error)
completion(.failure(error))
return
}
if let metadata = metadata {
completion(.success(metadata))
}
}
}
func getLinkMetadata(link: (String, String)) {
for storedLink in self.links {
if storedLink.id != link.1 {
return
}
}
do {
let detector = try NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue)
let matches = detector.matches(in: link.0, options: [], range: NSRange(location: 0, length: link.0.utf16.count))
if let match = matches.first {
guard let range = Range(match.range, in: link.0) else { return }
let uRLString = link.0[range]
self.fetchMetadata(for: String(uRLString)) { result in
self.handleLinkFetchResult(result, link: link)
}
}
} catch {
print(error)
}
}
private func handleLinkFetchResult(_ result: Result<LPLinkMetadata, Error>, link: (String, String)) {
DispatchQueue.main.async {
switch result {
case .success(let metadata):
self.createLink(with: metadata, id: link.1)
case .failure(let error):
print(error.localizedDescription)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
和链接类:
import Foundation
import LinkPresentation
class Link: NSObject, NSSecureCoding, Identifiable {
var id: String?
var metadata: LPLinkMetadata?
override init() {
super.init()
}
// MARK: - NSSecureCoding Requirements
static var supportsSecureCoding = true
func encode(with coder: NSCoder) {
guard let id = id, let metadata = metadata else { return }
coder.encode(id, forKey: "id")
coder.encode(metadata as NSObject, forKey: "metadata")
}
required init?(coder: NSCoder) {
id = coder.decodeObject(forKey: "id") as? String
metadata = coder.decodeObject(of: LPLinkMetadata.self, forKey: "metadata")
}
}
Run Code Online (Sandbox Code Playgroud)
这就是我得到的:
ali*_*ego 10
对我有用的解决方案是子类化 linkView 并覆盖内在内容大小。感谢 user1046037 的评论,使用 super.intrinsicContentSize.height 将使其能够动态工作。
import SwiftUI
import LinkPresentation
class CustomLinkView: LPLinkView {
override var intrinsicContentSize: CGSize { CGSize(width: 0, height: super.intrinsicContentSize.height) }
}
struct LinkViewRepresentable: UIViewRepresentable {
typealias UIViewType = CustomLinkView
var metadata: LPLinkMetadata?
func makeUIView(context: Context) -> CustomLinkView {
guard let metadata = metadata else { return CustomLinkView() }
let linkView = CustomLinkView(metadata: metadata)
return linkView
}
func updateUIView(_ uiView: CustomLinkView, context: Context) {
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1667 次 |
最近记录: |