Chapters

Hide chapters

macOS by Tutorials

First Edition · macOS 12 · Swift 5.5 · Xcode 13

Section I: Your First App: On This Day

Section 1: 6 chapters
Show chapters Hide chapters

16. Distributing Externally
Written by Sarah Reichelt

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

In the last chapter, you looked at the advantages and disadvantages of distributing your app through the Mac App Store. Then, you worked through the process of testing, distributing and updating using the Apple system.

Not all apps are eligible for the Mac App Store, and there are other reasons why you might want to distribute externally. In this chapter, you’ll look at what you need to do to distribute your app outside the App Store.

If you only want to use the Mac App Store, you can skip this chapter. Come back to it if you change your mind.

Apple’s Gatekeeper

macOS has a system called Gatekeeper to help protect our Macs from malware.

Open System Preferences ▸ Security & Privacy. In the General tab, you’ll see Allow apps downloaded from:. This is where you configure Gatekeeper:

Configuring Gatekeeper
Configuring Gatekeeper

There used to be an option to allow apps from anywhere, but Apple has locked that down. Now, you only have two options: App Store or App Store and identified developers.

To include your app in the identified developers category, it must be code signed and notarized. You upload the app archive to Apple for their servers to notarize it.

In the previous chapter, you created an Apple Developer account and linked it to Xcode. If you skipped that section, go back and do it now, so that you can be one of these identified developers. :]

You’ll need an Xcode project to work with. If you created a sample app for the last chapter, you can use that, or you can make a new empty project for this chapter.

Open your project in Xcode and make sure you’ve selected your Team in the project’s target settings under Signing & Capabilities.

While you’re there, make sure that Hardened Runtime is enabled. This does even more work to lock down your app and protect your users from malicious code. Apple will not notarize an app without this.

If you can’t see a Hardened Runtime section in Signing & Capabilities, click + Capability and double-click Hardened Runtime in the palette to add it.

Enabling hardened runtime
Enabling hardened runtime

By default, Xcode leaves all the options unchecked, but if your app uses any of the listed features, you’ll have to check them.

Change the Build in the target settings General tab. If you’re using numbers, you can increment this. Otherwise, update it using whatever scheme you prefer.

It’s a good idea to get into the habit of changing the build before starting any new distribution step. Even if the app is unchanged, it’s best to have different builds for App Store distribution and external distribution because they get processed differently.

Now, use Product ▸ Archive to create a new archive in the Organizer window.

Exporting the App

In the Organizer ▸ Archives window, click Distribute App to see the four possibilities:

Distribution options
Fowvbudoyauz odcaeym

Can't run app
Yuh'c hoy amm

App Translocation
Egw Nqosttaluquor

Notarizing the App

The only option you haven’t looked at yet is Developer ID. That’s the one which allows you to send your app off to the Apple notary service so they can confirm it’s clean. This isn’t the same as app review. Apple only checks that your app does not contain any harmful code.

upload summary
aqbeig feygawp

Organizer window
Udyohohex pucseg

Wrapping Your App

You’ve exported the app and it looks like a file, but actually, it’s a folder. See what’s inside by right-clicking the app and selecting Show Package Contents:

App package contents
Omk hedjepo pighejzw

Compressing
Ceytsivqopc

Creating a Disk Image

Setting up a disk image, or DMG, is a three-step process:

Creating a disk image
Xyuuzedx a pifw ucoca

Applications
Ohrxoqexeafh

Configuring the Display

Now, your image has two visible items, but the next thing you’ll add will be invisible. Disk images frequently have a background image with instructions or logos. You can use whatever image you like, but if you don’t have one, open the assets folder in the downloaded materials for this chapter and locate background.png.

View options
Tuex ocjourf

Setting the background picture.
Yidhiby xfe zizvvsaoqc hevwino.

Hiding Finder options
Nunohf Kuzrif eyjoepq

Disk image window
Nuhh aduga maljiq

Locking it Down

The final step is to lock your disk image by creating a read-only copy of it.

Converting the disk image.
Tepnicwenc jgo tiqk obowa.

Further Notarizing

Some sources suggest you should also notarize the disk image or zip file. I have not found this to be necessary, but if you want to do it, there are detailed instructions in Chapter 14 of Catalyst by Tutorials.

Selling Your App

You’ve prepared the app for distribution. Apple’s notary service has approved it and you’ve packaged it ready for downloads. Now what?

Releasing Updates

When distributing your app externally, you need to solve the problem of updates. In the App Store, updates get pushed out to users automatically, but when you’re distributing yourself, you have to handle this.

func versionAndBuild() -> String {
  if
    let bundleInfo = Bundle.main.infoDictionary,
    let version = bundleInfo["CFBundleShortVersionString"] as? String,
    let build = bundleInfo["CFBundleVersion"] as? String {
    return "Version: \(version) (\(build))"
  }
  return "Version: unknown"
}

Troubleshooting

Sadly, you don’t get crash reports for apps from outside the App Store. People can still make reports, but these disappear into the Apple servers, never to be seen again.

func emailDeveloper() {
  // 1
  let subject = "Really Useful App \(versionAndBuild())"
    // 2
    .addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!

  // 3
  let link = "mailto:dev@example.com?subject=\(subject)"

  // 4
  if let url = URL(string: link) {
    NSWorkspace.shared.open(url)
  }
}

Key Points

  • While distributing outside the App Store frees you from some constraints, you still need to get Apple to notarize your apps.
  • An app is actually a folder, so you need to wrap it for distribution.
  • Handling payments for the app is now your responsibility, although there are resellers that can help.
  • You’ll have to implement a process for getting updates out to your app’s users.
Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2024 Kodeco Inc.

You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now