Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 15 additions & 130 deletions documentation/customization/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,27 @@ title: Customizing Sparkle
---
## Customizing Sparkle

Here are the main routes by which you can bend Sparkle's behavior to your will:
Besides the `SUFeedURL` and `SUPublicEDKey` options, Sparkle will choose defaults for your app's update behavior. However you can change these settings if you want different behavior.

For example:

* If you do not want Sparkle to prompt the user (on second app launch) asking for permission if your app can check for updates automatically in the background, set `SUEnableAutomaticChecks` in your app's Info.plist.
* If you want Sparkle to automatically download and install updates silently in the background instead of notifying users of updates every time by default, enable `SUAutomaticallyUpdate` in your app's Info.plist.

Some of the Info.plist settings below are also paired with an updater API to change the settings at runtime, like `SUEnableAutomaticChecks` with [automaticallyChecksForUpdates](/documentation/api-reference/Classes/SPUUpdater.html#/c:objc(cs)SPUUpdater(py)automaticallyChecksForUpdates). The Info.plist settings are meant for default configuration, while the runtime APIs are in response to user setting changes. Please do not use the runtime APIs for setting initial default behavior. Check how to [add update settings](/documentation/preferences-ui/) for examples on changing user settings.

### Info.plist Settings

{:.table .table-bordered}
| Key | Type | Value |
| --- | ---- | ----- | ------- |
| `SUFeedURL` | String | The URL of your appcast, e.g. `https://example.com/appcast.xml`. It's recommended to always set it in Info.plist, even if you change it later programmatically. |
| `SUFeedURL` | String | The URL of your appcast, e.g. `https://example.com/appcast.xml`. It's recommended to set it in Info.plist, even if you change it later programmatically. |
| `SUPublicEDKey` | String | The base64-encoded public EdDSA key. Use Sparkle's `generate_keys` tool to get it. |
| `SUEnableAutomaticChecks` | Boolean | By default when this is not set, automatic checking for updates is initially disabled but users will be prompted for permission for Sparkle to check for updates automatically on second launch. If permission is granted, automatic checks for updates then becomes enabled. As of Sparkle 2.4 or later, the user will also have an option to opt into or out of automatic downloading of updates; the default state is based on the `SUAutomaticallyUpdate` setting.<br/>Setting this to `YES` enables automatic checking for updates (but not installation) by default, without asking your users for permission first.<br>Setting this to `NO` disables automatic checking for updates by default, also without asking your users for permission.<br/>This default property can later be overridden by setting [automaticallyChecksForUpdates](/documentation/api-reference/Classes/SPUUpdater.html#/c:objc(cs)SPUUpdater(py)automaticallyChecksForUpdates) in response to user setting changes. |
| `SUEnableSystemProfiling` | Boolean | Default: `NO`. Enables anonymous system profiling. See [System Profiling](/documentation/system-profiling) for more. |
| `SUScheduledCheckInterval` | Number | The number of seconds between updates. The default is `86400` (1 day). Setting to 0 disables updates.<br /><br />**Note:** this has a minimum bound of 1 hour in order to keep you from accidentally overloading your servers. |
| `SUEnableAutomaticChecks` | Boolean | By default when this is not set, automatic checking for updates is initially disabled but users will be prompted for permission for Sparkle to check for updates automatically on second launch. If permission is granted, automatic checks for updates then becomes enabled. As of Sparkle 2.4 or later, the user will also have an option to opt in or out of automatic downloading of updates; the default state is based on the `SUAutomaticallyUpdate` setting.<br/>Setting this to `YES` enables automatic checking for updates (but not installation) by default, without asking your users for permission first.<br>Setting this to `NO` disables automatic checking for updates by default, also without asking your users for permission.<br/>This default property can later be overridden by setting [automaticallyChecksForUpdates](/documentation/api-reference/Classes/SPUUpdater.html#/c:objc(cs)SPUUpdater(py)automaticallyChecksForUpdates) in response to user setting changes. |
| `SUScheduledCheckInterval` | Number | The number of seconds between updates. The default is `86400` (1 day).<br /><br />**Note:** this has a minimum bound of 1 hour in order to keep you from accidentally overloading your servers. |
| `SUAutomaticallyUpdate` | Boolean | Default: `NO`. Enables automatic download and installation of updates by default. If set to `YES`, Sparkle will attempt to download and install new updates silently in the background. Updates may be downloaded but not installed automatically if authorization is required. If the application hasn't quit for 1 week the user will be presented with installing the downloaded update (unless the updater delegate overrides this).<br/>This default property can later be overridden by setting [automaticallyDownloadsUpdates](/documentation/api-reference/Classes/SPUUpdater.html#/c:objc(cs)SPUUpdater(py)automaticallyDownloadsUpdates) in response to user setting changes (for example, the standard update alert has a checkbox for changing this).
| `SUAllowsAutomaticUpdates` | Boolean | By default, Sparkle automatically presents your users with the *option* to allow to automatically download and install any available updates if automatic checking of updates is enabled.<br/>Set this to `NO` to disallow automatic updates and require manual installation every time.<br/>Set this to `YES` to always allow automatic updates even if automatic checking of updates is disabled. |
| `SUAutomaticallyUpdate` | Boolean | Default: `NO`. Enables automatic download and installation of updates by default. If set to `YES`, Sparkle will attempt to download and install new updates silently in the background. In Sparkle 1, updates won't be opted into this if users need to provide authorization. In Sparkle 2, updates will be downloaded but not installed automatically if authorization is required. In all versions of Sparkle, if the application hasn't quit for 1 week the user will be presented with installing the downloaded update (unless the updater delegate overrides this).<br/>This default property can later be overridden by setting [automaticallyDownloadsUpdates](/documentation/api-reference/Classes/SPUUpdater.html#/c:objc(cs)SPUUpdater(py)automaticallyDownloadsUpdates) in response to user setting changes.
| `SUEnableSystemProfiling` | Boolean | Default: `NO`. Enables anonymous system profiling. See [System Profiling](/documentation/system-profiling) for more. |
| `SUVerifyUpdateBeforeExtraction` | Boolean | Default: `NO`. Set this to `YES` to force verification of updates before Sparkle extracts the downloaded update. Use this setting if you want stronger update validation and you aren't likely to lose access to your private EdDSA key (typically stored inside the macOS Keychain). EdDSA signing is required to use this setting. [Key rotation](/documentation/#rotating-signing-keys) is still possible by using Apple Developer ID code signed disk images as fallback. This setting is available in Sparkle 2.7 and later. |
| `SUShowReleaseNotes` | Boolean | Default: `YES`. Set this to `NO` to hide release notes display from the update alert. |
| `SUAllowedURLSchemes` | Array of Strings | An array of custom URL schemes allowed to be clicked from Sparkle's release notes view. By default, Sparkle only allows clicks to links that have a safe known URL scheme (like `https`). This setting is available in Sparkle 2.5 and later.
Expand All @@ -39,128 +46,6 @@ Here are the Info.plist settings relevant to use for Sandboxed applications usin
| `SUEnableInstallerConnectionService` | Boolean | Default: `NO`. Set this to `YES` to enable using the Installer Connection Service. This service is usually not needed due to being able to [add a mach name lookup exception entitlement](/documentation/sandboxing#installer-connection--status-services) instead. This service is not included in Sparkle's framework distribution by default. |
| `SUEnableInstallerStatusService` | Boolean | Default: `NO`. Set this to `YES` to enable using the Installer Status Service. This service is usually not needed due to being able to [add a mach name lookup exception entitlement](/documentation/sandboxing#installer-connection--status-services) instead. This service is not included in Sparkle's framework distribution by default. |

### Sparkle 2 APIs

Please visit the [Sparkle 2 API Reference](/documentation/api-reference).

### Sparkle 1 APIs

#### Calls to SUUpdater

The `SUUpdater` object is the main controller for the updating system in your app. There is a singleton instance of this class for each bundle being updated. If you're trying to update the running .app, you can retrieve the appropriate `SUUpdater` by calling `[SUUpdater sharedUpdater]`. If you're trying to update some [other bundle](/documentation/bundles/), you can use `[SUUpdater updaterForBundle:(NSBundle *)myBundle]`.

Once you have the `SUUpdater` instance, there are a few interesting accessors you could use. Please use them only if you need dynamic behavior (e.g. user preferences). Do not use these functions to set default configuration. Use Info.plist keys to set default configuration instead.

```objc
- (void)setAutomaticallyChecksForUpdates:(BOOL)automaticallyChecks;
- (BOOL)automaticallyChecksForUpdates;

- (void)setUpdateCheckInterval:(NSTimeInterval)interval;
- (NSTimeInterval)updateCheckInterval;

- (void)setFeedURL:(NSURL *)feedURL;
- (NSURL *)feedURL;

- (void)setSendsSystemProfile:(BOOL)sendsSystemProfile;
- (BOOL)sendsSystemProfile;

- (void)setAutomaticallyDownloadsUpdates:(BOOL)automaticallyDownloadsUpdates;
- (BOOL)automaticallyDownloadsUpdates;
```

There is a risk of race conditions. If you want to make sure these settings are changed before the first automatic update check, you should do this in the `NSApplication` delegate method `-applicationWillFinishLaunching:`. For a non-app bundle you should then make the changes immediately after you first create the `SUUpdater` instance in your code.

A few more methods of interest:

```objc
// This IBAction is meant for a main menu item. Hook up any menu item to this action,
// and Sparkle will check for updates and report back its findings through UI.
- (IBAction)checkForUpdates:sender;

// This kicks off an update meant to be programmatically initiated. That is,
// it will display no UI unless it actually finds an update, in which case it
// proceeds as usual. If the automated downloading is turned on, however,
// this will invoke that behavior, and if an update is found, it will be
// downloaded and prepped for installation.
//
// You do not need to call this. Sparkle calls it automatically according to
// the update schedule.
- (void)checkForUpdatesInBackground;

// This begins a "probing" check for updates which will not actually offer to
// update to that version. The delegate methods, though, (up to updater:didFindValidUpdate:
// and updaterDidNotFindUpdate:), are called, so you can use that information in your UI.
// Essentially, you can use this to UI-lessly determine if there's an update.
- (void)checkForUpdateInformation;

// Date of last update check. Returns nil if no check has been performed.
- (NSDate *)lastUpdateCheckDate;

// Call this to appropriately schedule or cancel the update checking timer according
// to the preferences for time interval and automatic checks. If this SUUpdater instance
// was not present during the application's launch, you must call this method to start
// the update cycle explicitly.
- (void)resetUpdateCycle;

- (BOOL)updateInProgress;

- (void)setDelegate:(id)delegate; // See below for more information on the delegate.
- delegate;
```

#### SUUpdater delegate methods

You can control the SUUpdater's behavior a little more closely by providing it with a delegate. Here are the delegate methods you might implement:

```objc
// Use this to override the default behavior for Sparkle prompting the
// user about automatic update checks. You could use this to make Sparkle
// prompt for permission on the first launch instead of the second.
- (BOOL)updaterShouldPromptForPermissionToCheckForUpdates:(SUUpdater *)bundle;

- (void)updater:(SUUpdater *)updater didFinishLoadingAppcast:(SUAppcast *)appcast;

// If you're using special logic or extensions in your appcast, implement
// this to use your own logic for finding a valid update, if any, in the given appcast.
- (SUAppcastItem *)bestValidUpdateInAppcast:(SUAppcast *)appcast
forUpdater:(SUUpdater *)bundle;

- (void)updater:(SUUpdater *)updater didFindValidUpdate:(SUAppcastItem *)update;
- (void)updaterDidNotFindUpdate:(SUUpdater *)update;

// Sent immediately before installing the specified update.
- (void)updater:(SUUpdater *)updater willInstallUpdate:(SUAppcastItem *)update;

// Return YES to delay the relaunch until you do some processing.
// Invoke the provided NSInvocation to continue the relaunch.
- (BOOL)updater:(SUUpdater *)updater
shouldPostponeRelaunchForUpdate:(SUAppcastItem *)update
untilInvoking:(NSInvocation *)invocation;

// Called immediately before relaunching.
- (void)updaterWillRelaunchApplication:(SUUpdater *)updater;

// Called if the application has been relaunched from an update
- (void)updaterDidRelaunchApplication:(SUUpdater *)updater;

// This method allows you to provide a custom version comparator.
// If you don't implement this method or return nil, the standard version
// comparator will be used. See SUVersionComparisonProtocol.h for more.
- (id <SUVersionComparison>)versionComparatorForUpdater:(SUUpdater *)updater;

// Returns the path which is used to relaunch the client after the update
// is installed. By default, the path of the host bundle.
- (NSString *)pathToRelaunchForUpdater:(SUUpdater *)updater;

// This method allows you to add extra parameters to the appcast URL,
// potentially based on whether or not Sparkle will also be sending along
// the system profile. This method should return an array of dictionaries
// with keys: "key", "value", "displayKey", "displayValue", the latter two
// being human-readable variants of the former two.
- (NSArray *)feedParametersForUpdater:(SUUpdater *)updater
sendingSystemProfile:(BOOL)sendingProfile;
```

#### Other options
### Sparkle APIs

If these methods aren't enough to do what you need, you're going to have to dig into Sparkle's code. You might start by creating a different update driver: check out SUBasicUpdateDriver.h to get an idea.
Please visit the [Sparkle 2 API Reference](/documentation/api-reference) for full documentation on class and delegate APIs.
56 changes: 8 additions & 48 deletions documentation/preferences-ui/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,18 @@ id: documentation
title: Adding a Settings UI
---

## Sparkle 2

### Adding a Settings UI in Cocoa
## Adding a Settings UI in Cocoa

These instructions below are for adding settings in a Cocoa nib and assume you have a Settings nib with its `File's Owner` being set to your Settings controller class (e.g, a `NSWindowController` subclass). The controller class should have an `updater` property set to your application's `SPUUpdater`, which may be passed from your application's delegate.

#### Enable automatic checking
### Enable automatic checking

* Drag a check button from the Library to your document.
* Set the title to something like "Automatically check for updates".
* Select the check button, and under the Bindings tab, select Value.
* Check the Bind to: check button, choose `File's Owner` from the popup, and set the Model Key Path to `updater.automaticallyChecksForUpdates`.

#### Update check interval
### Update check interval

* Drag a popup button from the Library to your document.
* Set the titles of the menu items to e.g. "Hourly", "Daily", "Weekly", "Monthly".
Expand All @@ -26,11 +24,11 @@ These instructions below are for adding settings in a Cocoa nib and assume you h
* Check the Bind to: check button, choose `File's Owner` from the popup, and set the Model Key Path to `updater.updateCheckInterval`.
* Select Enabled, check the Bind to: check button, choose `File's Owner` from the popup, and set the Model Key Path to `updater.automaticallyChecksForUpdates`.

#### Other settings
### Other settings

Follow directions similar to [Enable automatic checking](#enable-automatic-checking) to bind a check button to `updater.sendsSystemProfile` or `updater.automaticallyDownloadsUpdates`. See [customization](/documentation/customization/#infoplist-settings) for details on the available keys.
Follow directions similar to [Enable automatic checking](#enable-automatic-checking) to bind a check button to `updater.automaticallyDownloadsUpdates` or `updater.sendsSystemProfile`. See [customization](/documentation/customization/#infoplist-settings) for details on the available keys.

### Adding Settings in SwiftUI
## Adding Settings in SwiftUI

This is a continuation from [Creating an Updater in SwiftUI](/documentation/programmatic-setup#create-an-updater-in-swiftui).

Expand Down Expand Up @@ -81,7 +79,7 @@ var body: some Scene {
}
```

### Adding Settings in Qt
## Adding Settings in Qt

This is a continuation from [Creating an Updater in Qt](/documentation/programmatic-setup#create-an-updater-in-qt) and illustrates one way of adding updater settings.

Expand Down Expand Up @@ -144,44 +142,6 @@ Note that [automaticallyChecksForUpdates](/documentation/api-reference/Classes/S

---

## Sparkle 1

These instructions below are for adding settings in a Cocoa nib and assume you have a Settings nib with its `File's Owner` being set to your Settings controller class (e.g, a `NSWindowController` subclass). The controller class should have an `updater` property set to your application's `SUUpdater`, which may be passed from your application's delegate.

### Enable automatic checking

* Drag a check button from the Library to your document.
* Set the title to something like "Automatically check for updates".
* Select the check button, and under the Bindings tab, select Value.
* Check the Bind to: check button, choose `File's Owner` from the popup, and set the Model Key Path to `updater.automaticallyChecksForUpdates`.

### Update check interval

* Drag a popup button from the Library to your document.
* Set the titles of the menu items to e.g. "Hourly", "Daily", "Weekly", "Monthly".
* Set the tags of the menu items to the corresponding times in seconds, e.g. 3600, 86400, 604800, 2629800.
* Select the popup button, and under the Bindings tab, select Selected Tag.
* Check the Bind to: check button, choose `File's Owner` from the popup, and set the Model Key Path to `updater.updateCheckInterval`.
* Select Enabled, check the Bind to: check button, choose `File's Owner` from the popup, and set the Model Key Path to `updater.automaticallyChecksForUpdates`.

### Other settings

Follow directions similar to [Enable automatic checking](#enable-automatic-checking). to bind a check button to `sendsSystemProfile` or `automaticallyDownloadsUpdates`. See [customization](/documentation/customization/#infoplist-settings) for details on the available keys.

### Settings for non-app bundles

These directions do not work for non-app bundles, as the updater you add to the nib will be the `sharedUpdater` for the application bundle. To be able to bind to the updater for your bundle, you can add the following accessor to your settings controller (the owner of the nib):

```objc
- (SUUpdater *)updater {
return [SUUpdater updaterForBundle:[NSBundle bundleForClass:[self class]]];
}
```

Then just bind the controls to the File's Owner, and start the Model Key Path with updater., e.g. updater.automaticallyChecksForUpdates.

---

### Watch out for Preference Caching
## Watch out for Preference Caching

macOS caches plist files in `~/Library/Preferences`, so don't edit them directly. If you want to tweak these files for testing (e.g. change last update check date), use the `defaults` command.
Loading