What's in here?
- A convenient model to talk about
Update
s andVersion
s, - a UI to display your update notices in,
- and
UserDefaults
extensions so the user only sees the messages when she needs to.
Requires macOS 10.11+
You tell WhatsNew
about the current settings and then let it figure out if it needs to display the "What's New" update window or not.
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Figures out settings & app version from UserDefaults.standard
// and Bundle.main:
let whatsNew = WhatsNew(configuration: .standardMain)
// Set up information about the latest "What's New"-worthy version:
let update = Update(version: Version(2, 2, 0), view: aViewWithAllInfos)
// Show the update notice if the criteria match and store
// the version information in UserDefaults.standard for the next run.
whatsNew.displayIfNeededAndRegister(update: update)
}
- Use arrow keys to navigate
- Use Escape or ⌘+. to close
The window may change its size to accommodate each update view, but the navigation controls stay in place on screen so your users don't have to awkwardly hunt down the "Next" button again and again.
v2.2.0 | v1.8.0 | |
---|---|---|
Dark | ||
Light |
The main intention of WhatsNewKit is to display update information to existing users.
- Upon first launch of your app, WhatsNewKit is supposed to not display a "What's New" window.
- Existing users will only get new update notices exactly once.
This works with one or multiple updates that have been missed.
There's not much you need to know that Xcode's code completion won't tell you, but here's a description anyway.
You can create WhatsNew.Configuration
in 3 ways:
- Manually, e.g. for testing or when you want to obtain the information from a different source:
.init(isFirstLaunch:appVersion:lastWhatsNewVersion:)
- Reading values from
UserDefaults
andBundle
:.init(userDefaults:appBundle:)
- Reading values from the main bundle and standard user defaults:
.standardMain
To create an Update
, you use one of its designated initializers:
Update.init(version:windowTitle:view:)
to pass it anyNSView
directly, orUpdate.init(version:windowTitle:viewContainer:)
to pass it aViewContainer
-conforming object, like aNSViewController
you get from a Nib. (See below for Nib details.)
The parameter windowTitle
is optional in all of these.
The resulting view will be displayed in the content section of the NSWindow
of this framework
Armed with a Configuration
and Update
instances, you can create a WhatsNew
instance and make it displayIfNeededAndRegister(updates:)
.
⚠️ Heads Up with the View Design⚠️ Your views need to be laid-out very strict so that inserting them into the window using Auto Layout affects the window size appropriately. If your size or position constraints have a priority ofNSLayoutPriorityWindowSizeStayPut
, which is known to be500
, then the window will not size to fit the content. I found multi-line labels to be especially cumbersome and recommend you set an explicit size if you can.
You can pass any NSView
subclass to Update.init(version:windowTitle:view:)
, no matter if it's loaded from a Storyboard, Nib, or created in code.
Nibs work especially well! 🎉
Look at the example app in this project for inspiration.
The trick is this:
- Create a
UpdateViewFromNib
wrapper: It loads aNSViewController
from a Nib and obtains its main view.UpdateViewFromNib.init(nibName:bundle:)
behaves like theNSViewController
initializer.UpdateViewFromNib.init(version:bundle:)
assumes the Nib file is calledWhatsNew_vX_Y_Z
, where X, Y, and Z are the major, minor, and patch version component of yourVersion
object respectively. (Version(1,8,0)
resolves toWhatsNew_v1_8_0.xib
.)
- Use the variant
Update.init(version:windowTitle:viewContainer:)
to pass theUpdateViewFromNib
object in as theviewContainer
directly for your convenience.
You can offer your app users an affordance, e.g. a menu item, to display what's new regardless of the setting.
- Use
WhatsNew.display(update:)
to show exactly one version information. - Use
WhatsNew.display(updates:)
(note the plural!) to show multiple version informations.
Use WhatsNew.displayIfNeeded(update:)
or WhatsNew.displayIfNeeded(updates:)
to let WhatsNewKit figure out if the user needs to see any update info.
Copyright (c) 2019--2020 Christian Tietze. Distributed under the MIT License.