Skip to content

jnutting/AppStoreCatalog

Repository files navigation

AppStoreCatalog

AppStoreCatalog implements a GUI for displaying multiple App Store products in a scrolling grid. By tapping on a product, the user is taken to a page where they can see more info about the app, and optionally purchase it using SKStoreProductViewController. In a narrow space like an iPhone, the grid is shown as a single column. In a wider space such as an iPad, it will expand to more columns.

This project is a SwiftUI rewrite/replacement of an older package called MultiProductViewer.

screenshot

Background:

This functionality was originally (in iOS 5 and iOS 6) implemented by SKStoreProductViewController itself. You could just pass it your company identifier, and it would present all of your company's products in a list, and let the user drill down to get more info and purchase apps. That functionality stopped working in iOS 7 due to a bug; It was later restored in iOS 8, but by that time I had already created my own library, the now defunct MultiProductViewer, which was more flexible and useful than Apple's own. AppStoreCatalog is a re-implementation which does even more.

What it does:

Instead of just imitating the old behavior, AppStoreCatalog improves upon it by showing a larger icon, and giving the user the ability to include a small piece of text for each app. It also lets you pick exactly which apps you want to show by supplying multiple lists of your own. This can be used to promote not only your own company's apps, but also groups of apps belonging to clients or friends, or just any apps you like for any reason :)

In the simplistic way of doing things that SKStoreProductViewController includes, you just provide a company identifier, and StoreKit does the rest. Since that's not really feasible from the client side using public APIs, AppStoreCatalog requires you to provide four pieces of data for each app you want to show: A name, an App Store identifier, an icon URL, and a string containing a brief description.

The configuration can be easily specified using JSON data, as described later in this document.

How it looks:

Here's the iPhone layout, presented with .sheet(): screenshot

Here's the iPad layout, presented with .fullScreenCover(): screenshot

Usage:

Start off by importing this SPM package into your project in the usual way, using this URL.

Then, create a JSON file with the following structure, containing information for the products you want to display, as shown below. The images referenced as URLs will be sized to fit a screen size of a 100-point square. Most screens in use on modern devices have a pixel density of at least two pixels per point, so it's recommended to use images that are roughly 200x200.

The JSON can be contained within your project or hosted on a server, it's up to you.

{ "productGroups" : [
    {   "title" : "Awesome Games",
        "products" : [
            {
                "name" : "FlippyBit",
                "details" : "Party like it's 1979! Flippy Bit makes one of 2014's biggest mobile hits look like it's on an old Atari.",
                "identifier" : "825459863",
                "imageURL" : "https://rebisoft.com/appicons/flippybit512.png"
            },
            {
                "name" : "Pits of Death",
                "details" : "Find your way through a mysterious dungeon. Find the arrow and defeat the dragon before you fall into a pit!",
                "identifier" : "989109750",
                "imageURL" : "https://rebisoft.com/appicons/PitsOfDeathIcon128.png"
            },
        ]
    },
    {   "title" : "Other Apps",
        "products" : [
            {
                "name" : "Goldy",
                "details" : "Goldy is a web browser for iPhone, iPad, and iPod touch that offers one simple feature: Privacy.",
                "identifier" : "417317449",
                "imageURL" : "https://rebisoft.com/_Media/screen_shot_2011-08-19_at_med.png"
            },
        ]
    },
]}

In your application, import this framework into the view where you want to display it:

import AppStoreCatalog

Prepare the catalog data somewhere:

    // In production code, please do better than just "try!" as shown in this
    // snippet! 
    let data = try! Data(contentsOf: Bundle.main.url(forResource: "ExampleCatalog",
                                                     withExtension: "json")!)
    // ... or ...
    let url = URL(string: "https://sample.com/all_products.json")!
    let (data, response) = try await URLSession.shared.data(from: url)
    
    let catalog = try! AppStoreCatalog(data: data) 

When you want to display the view, do something like this. The closure is optional; If it's provided, it will be called any time StoreKit fails to show a product page.

    // assuming the existence of `@State var presentingSheet`...
    .sheet(isPresented: $presentingSheet) {
        AppStoreCatalogView(catalog: catalog) { identifier, error in
            print("AppStoreCatalogView failed to show App Store view for product \(identifier):\n\(error.localizedDescription)")
        }
    }

It's also possible to choose whether or not AppStoreCatalogView will include a close button. This is not typically necessary for presentation within a Sheet, but is definitely useful for a full screen presentation. See the included example application for full usage details and examples.

Additional notes

Tapping on a displayed product will attempt to display StoreKit's purchase page for that product. If the product's identifier is invalid or cannot be found on the app store for any reason, a message will be displayed to the user. You can also give AppStoreCatalogView a closure to be called whenever this happens, in case you want to log this in some way.

Due to StoreKit limitations, every attempt to display a purchase page fails when running in the Simulator, so you'll see the failure message for every product. Run on a device to see it actually work.

AppStoreCatalog builds and runs on macOS, but it doesn't seem to function quite correctly as of yet, probably due to the maintainer's lack of experience with the macOS incarnation of SwiftUI. This may be fixed in the future, but for now, consider the macOS support here "experimental". Pull requests to improve this, or any other aspect of this package, are welcome!

About

Swift package providing a SwiftUI view for displaying a catalog of App Store products

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages