According to WWDC20 and other articles it seems its quite easy to fetch the image url from a given url. Below is my starter code. That just lists a random list of urls and is supposed to fetch the imageurl for the rich link previews of the urls. One simply fetches the metadata using the LPMetadataProvider. But i can't get it to show the image url. Does someone know how its done in SwiftUI?
import SwiftUI
import LinkPresentation
struct ExampleHTTPLinks: View {
    var links = [ "https://www.google.com", "https://www.hotmail.com"]
    let metadataProvider = LPMetadataProvider()
    
    
    var body: some View {
        
        
        List(links, id:\.self) { item in
            HStack {
                Text(item)
                Image(systemName: "heart.fill")
                metadataProvider.startFetchingMetadata(for: URL(string: item)!) { metadata, error in
                  if error != nil {
                    // The fetch failed; handle the error.
                    // Examples: server doesn't respond, is too slow, user doesn't have network.
                    return
                  }
                 let linkView = LPLinkView(metadata: metadata)
                    Image(linkView.image)
                  // Make use of the fetched metadata.
                }
            }
        }
    }
}
struct ExampleHTTPLinks_Previews: PreviewProvider {
    static var previews: some View {
        ExampleHTTPLinks()
    }
}
                Here's a working version:
class LinkViewModel : ObservableObject {
    let metadataProvider = LPMetadataProvider()
    
    @Published var metadata: LPLinkMetadata?
    @Published var image: UIImage?
    
    init(link : String) {
        guard let url = URL(string: link) else {
            return
        }
        metadataProvider.startFetchingMetadata(for: url) { (metadata, error) in
            guard error == nil else {
                assertionFailure("Error")
                return
            }
            DispatchQueue.main.async {
                self.metadata = metadata
            }
            guard let imageProvider = metadata?.imageProvider else { return }
            imageProvider.loadObject(ofClass: UIImage.self) { (image, error) in
                guard error == nil else {
                    // handle error
                    return
                }
                if let image = image as? UIImage {
                    // do something with image
                    DispatchQueue.main.async {
                        self.image = image
                    }
                } else {
                    print("no image available")
                }
            }
        }
    }
}
struct MetadataView : View {
    @StateObject var vm : LinkViewModel
    
    var body: some View {
        VStack {
            if let metadata = vm.metadata {
                Text(metadata.title ?? "")
            }
            if let uiImage = vm.image {
                Image(uiImage: uiImage)
                    .resizable()
                    .frame(width: 100, height: 100)
            }
        }
    }
}
struct ContentView: View {
    var links = [ "https://www.google.com", "https://www.hotmail.com"]
    let metadataProvider = LPMetadataProvider()
    
    var body: some View {
        List(links, id:\.self) { item in
            HStack {
                Text(item)
                Image(systemName: "heart.fill")
                MetadataView(vm: LinkViewModel(link: item))
            }
        }
    }
}
LPMetadataProvider complains if you try to use it for multiple calls, so I've moved it to a view model.
The image is vended by an NSImageProvider -- you can see the loadObject call is what gets the UIImage out of it.
Note that you could use LPLinkView if you wanted to use the out-of-the-box presentation that Apple gives you. Because it's a UIView, to use it in SwiftUI, you'd have to wrap it with UIViewRepresentable:
struct LPLinkViewRepresented: UIViewRepresentable {
    var metadata: LPLinkMetadata
    
    func makeUIView(context: Context) -> LPLinkView {
        return LPLinkView(metadata: metadata)
    }
    
    func updateUIView(_ uiView: LPLinkView, context: Context) {
        
    }
}
struct MetadataView : View {
    @StateObject var vm : LinkViewModel
    
    var body: some View {
        if let metadata = vm.metadata {
            LPLinkViewRepresented(metadata: metadata)
        } else {
            EmptyView()
        }
    }
}
class LinkViewModel : ObservableObject {
    let metadataProvider = LPMetadataProvider()
    
    @Published var metadata: LPLinkMetadata?
    
    init(link : String) {
        guard let url = URL(string: link) else {
            return
        }
        metadataProvider.startFetchingMetadata(for: url) { (metadata, error) in
            guard error == nil else {
                assertionFailure("Error")
                return
            }
            DispatchQueue.main.async {
                self.metadata = metadata
            }
        }
    }
}
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With