Swift framework to deal with licensing and time-based trial periods in macOS apps.

What's New

v3.3.2 Simpler URL Query Parsing


Instead of handling URL scheme requests magically, allows host apps to provide their own parser.

Might we suggest this parsing library? 🫴

Full Changelog: 3.3.1...3.3.2

Time-Based Trial App Licensing

Adds time-based trial and easy license verification using CocoaFob to your macOS app.

Carthage compatible

For setup instructions of your own store and app preparation with FastSpring, have a look at my book Make Money Outside the Mac App Store!


Swift Package Manager

dependencies: [
  .package(url: "", .upToNextMajor(from: Version(3, 0, 0))),

Add package depencency via Xcode by using this URL:

CocoaFob is automatically linked statically for you, no need to do anything.


  • Include the Trial and TrialLicense libraries in your project.
  • Include the CocoaFob (Swift 5) library in your project, too. (You have to link this in the app because a library cannot embed another library.)


  • Create an AppLicensing instance with licenseChangeBlock and invalidLicenseInformationBlock handling change events.
  • Set up and start the trial.


import TrialLicense

let publicKey = [
        "-----BEGIN DSA PUBLIC KEY-----\n",
        // ...
        "-----END DSA PUBLIC KEY-----\n"
let configuration = LicenseConfiguration(appName: "AmazingApp!", publicKey: publicKey)

class MyApp: AppLicensingDelegate {

    init() {

            configuration: configuration,
            initialTrialDuration: Days(30),

            // Set up the callbacks:
            licenseChangeBlock: self.licenseDidChange(licenseInfo:),
            invalidLicenseInformationBlock: self.didEnterInvalidLicenseCode(name:licenseCode:),

            // Get notified about initial state to unlock the app immediately:
            fireInitialState: true)

    func licenseDidChange(licenseInformation: LicenseInformation) {

        switch licenseInformation {
        case .onTrial(_):
            // Changing back to trial may be possible if you support unregistering
            // form the app (and the trial period is still good.)

        case .registered(_):
            // For example:
            //   displayThankYouAlert()
            //   unlockApp()

        case .trialUp:
            // For example:
            //   displayTrialUpAlert()
            //   lockApp()
            //   showRegisterApp()

    func didEnterInvalidLicenseCode(name: String, licenseCode: String) {

        // For example:
        //   displayInvalidLicenseAlert()
        // -- or show an error label in the license window.

let myApp = MyApp()


LicenseInformation reveals the state your app is in:

enum LicenseInformation {
    case registered(License)
    case onTrial(TrialPeriod)
    case trialUp

The associated types provide additional information, for example to display details in a settings window or show remaining trial days in the title bar of your app.

License represents a valid name--license code pair:

struct License {
    let name: String
    let licenseCode: String

TrialPeriod encapsulates the duration of the trial.

struct TrialPeriod {
    let startDate: Date
    let endDate: Date

TrialPeriod also provides these convenience methods:

  • ended() -> Bool
  • daysLeft() -> Days

... where Days encapsulates the remainder for easy conversion to TimeInterval and exposing userFacingAmount: Int for display.


Copyright (c) 2016 by Christian Tietze. Distributed under the MIT License. See the LICENSE file for details.


  • Swift Tools 5.5.0
View More Packages from this Author


Last updated: Wed Jun 05 2024 01:49:27 GMT-0900 (Hawaii-Aleutian Daylight Time)