Book

Exploring Freelancing

Navigate freelancing as a developer; find clients, manage contracts, ensure timely payment, and learn from experiences!


Exploring MusicKit

I wrote this book to fill in the gap for the documentation, filled with examples so that you do not have to spend time experimenting yourself.

I hope this book provides value to you and your app, and you enjoy working with MusicKit and integrating Apple Music into your app!

Use the discount code “early” for a massive 75% discount!

I want this!


I wrote a post last year on how you can get the artist artwork from Apple Music, which isn’t possible using the native MusicKit API.

For achieving that, I used the OpenGraph framework by Satoshi Takano to extract meta tags and fetch the image URL.

This post is about how you can use OpenGraph in your app.

From the website:

The Open Graph protocol enables any web page to become a rich object in a social graph. For instance, this is used on Facebook to allow any web page to have the same functionality as any other object on Facebook.

Installation

You can install the framework using SPM, Cocoapods, and Carthage. I use Swift Package Manager, so add the following line to your Package.swift:

https://github.com/satoshi-takano/OpenGraph.git

There’s a build error due to a recent commit for async/await syntax. I’ve sent a PR to fix it, and as a workaround, you can use my fork:

https://github.com/rudrankriyam/OpenGraph.git

Next, I’m listening to the song “Nothing” by Bruno Major, and we’ll show the meta tags from the Apple Music link:

https://music.apple.com/in/album/nothing/1500454251?i=1500454362

OpenGraphData Structure

We want the title, the image URL, the link to the song, the description, and the site’s name. So, let’s create a structure to hold this data:

struct OpenGraphData {
    var title: String?
    var link: URL?
    var type: String?
    var siteName: String?
    var description: String?
    var imageURL: URL?
}

Fetch Tags using OpenGraph

The framework OpenGraph has a static method fetch(url:headers:configuration:) where you provide the URL to extract the tags from, and it returns OpenGraph. It provides different cases under OpenGraphMetadata like title, type, image, URL, locale, etc.

You can also provide headers to the fetch method and URLSessionConfiguration as well:

func fetch(url: URL, headers: [String: String]? = nil, configuration: URLSessionConfiguration = .default) async throws-> OpenGraph

In a sample view, we’ll use the method to extract the data as follows:

import SwiftUI
import OpenGraph

struct ContentView: View {
    @State private var data = OpenGraphData()
    
    var body: some View {
        // View to fill later
        .task {
            await fetchData()
        }
    }
    
    private func fetchData() async {
        do {
            let songURL = "https://music.apple.com/in/album/nothing/1500454251?i=1500454362"
            guard let url = URL(string: songURL) else { return }
            
            let openGraph = try await OpenGraph.fetch(url: url)
        } catch {
            print(error)
        }
    }
}

From the variable openGraph, we fill the OpenGraphData structure, and then assign it to the state variable:

private func fetchData() async {
    do {
        let songURL = "https://music.apple.com/in/album/nothing/1500454251?i=1500454362"
        guard let url = URL(string: songURL) else { return }
        
        let openGraph = try await OpenGraph.fetch(url: url)
        
        let data = OpenGraphData(
            title: openGraph[.title],
            link: URL(string: openGraph[.url] ?? ""),
            type: openGraph[.type],
            siteName: openGraph[.siteName],
            description: openGraph[.description],
            imageURL: URL(string: openGraph[.image] ?? "")
        ) 
        
        self.data = data 
    } catch {
        print(error)
    }
}

Example View

Now, you can use and display the data however you want! Here’s a sample view that I created:

struct ContentView: View {
    @State private var data = OpenGraphData()
    
    var body: some View {
        VStack {
            if let siteName = data.siteName {
                Text(siteName)
                    .font(.largeTitle)
                    .bold()
            }
            
            AsyncImage(url: data.imageURL) { image in
                image
                    .resizable()
                    .scaledToFit()
            } placeholder: {
                ProgressView()
            }
            .cornerRadius(16)
            
            if let type = data.type {
                Text(type)
                    .font(.callout)
                    .italic()
            }
            
            if let title = data.title {
                Text(title)
                    .font(.title)
                    .bold()
            }
            
            if let description = data.description {
                Text(description)
                    .multilineTextAlignment(.center)
            }
            
            if let url = data.link {
                let string = "[Link to the song](\(url))"
                Text(try! AttributedString(markdown: string))
                    .padding()
            }
        }
        .padding()
        .task {
            await fetchData()
        }
    }
}

Running the app gives the following output:

Nothing by Bruno Majors on Apple Music showing from Meta tags

Conclusion

Using the OpenGraph Swift wrapper for Open Graph protocol, you access the attributes using subscript and enum cases. You can use the fetched tags as per your use cases.

Tag @rudrankriyam on Twitter! for sharing about your experience of using OpenGraph!

Thanks for reading, and I hope you’re enjoying it!

Book

Exploring Freelancing

Navigate freelancing as a developer; find clients, manage contracts, ensure timely payment, and learn from experiences!