一个 Swift 包,可以轻松展示你的应用程序的新功能。
从底层设计,可以完全根据你的需求进行自定义。
import SwiftUI
import WhatsNewKit
struct ContentView: View {
var body: some View {
NavigationView {
// ...
}
.whatsNewSheet()
}
}
要使用 Apple 的 Swift Package Manager 进行集成,请将以下内容作为依赖项添加到你的 Package.swift
中
dependencies: [
.package(url: "https://github.com/SvenTiigi/WhatsNewKit.git", from: "2.0.0")
]
或者,导航到你的 Xcode 项目,然后选择 Swift Packages
,点击 “+” 图标并搜索 WhatsNewKit
。
查看示例应用程序,了解 WhatsNewKit 的实际应用。只需打开 Example/Example.xcodeproj
并运行 "Example" 方案。
如果你希望手动呈现 WhatsNewView
,你可以使用 sheet(whatsNew:)
修饰符。
struct ContentView: View {
@State
var whatsNew: WhatsNew? = WhatsNew(
title: "WhatsNewKit",
features: [
.init(
image: .init(
systemName: "star.fill",
foregroundColor: .orange
),
title: "Showcase your new App Features",
subtitle: "Present your new app features..."
),
// ...
]
)
var body: some View {
NavigationView {
// ...
}
.sheet(
whatsNew: self.$whatsNew
)
}
}
自动呈现模式允许你通过 SwiftUI Environment 简单地声明你的新功能,并且 WhatsNewKit 将负责呈现相应的 WhatsNewView
。
首先,将 .whatsNewSheet()
修饰符添加到 WhatsNewView
应该被呈现的视图上。
struct ContentView: View {
var body: some View {
NavigationView {
// ...
}
// Automatically present a WhatsNewView, if needed.
// The WhatsNew that should be presented to the user
// is automatically retrieved from the `WhatsNewEnvironment`
.whatsNewSheet()
}
}
.whatsNewSheet()
修饰符使用 WhatsNewEnvironment
来检索一个可选的 WhatsNew 对象,该对象应该为当前版本呈现给用户。因此,你可以通过 environment
修饰符轻松配置 WhatsNewEnvironment
。
extension App: SwiftUI.App {
var body: some Scene {
WindowGroup {
ContentView()
.environment(
\.whatsNew,
WhatsNewEnvironment(
// Specify in which way the presented WhatsNew Versions are stored.
// In default the `UserDefaultsWhatsNewVersionStore` is used.
versionStore: UserDefaultsWhatsNewVersionStore(),
// Pass a `WhatsNewCollectionProvider` or an array of WhatsNew instances
whatsNewCollection: self
)
)
}
}
}
// MARK: - App+WhatsNewCollectionProvider
extension App: WhatsNewCollectionProvider {
/// Declare your WhatsNew instances per version
var whatsNewCollection: WhatsNewCollection {
WhatsNew(
version: "1.0.0",
// ...
)
WhatsNew(
version: "1.1.0",
// ...
)
WhatsNew(
version: "1.2.0",
// ...
)
}
}
WhatsNewEnvironment
将负责确定应该为当前版本呈现给用户的匹配的 WhatsNew 对象。
如前面的示例所示,你可以通过指定 WhatsNewVersionStore
并提供 WhatsNewCollection
来初始化 WhatsNewEnvironment
。
// Initialize WhatsNewEnvironment by passing an array of WhatsNew Instances.
// UserDefaultsWhatsNewVersionStore is used as default WhatsNewVersionStore
let whatsNewEnvironment = WhatsNewEnvironment(
whatsNewCollection: [
WhatsNew(
version: "1.0.0",
// ...
)
]
)
// Initialize WhatsNewEnvironment with NSUbiquitousKeyValueWhatsNewVersionStore
// which stores the presented versions in iCloud.
// WhatsNewCollection is provided by a `WhatsNewBuilder` closure
let whatsNewEnvironment = WhatsNewEnvironment(
versionStore: NSUbiquitousKeyValueWhatsNewVersionStore(),
whatsNewCollection: {
WhatsNew(
version: "1.0.0",
// ...
)
}
)
此外,WhatsNewEnvironment
还包括补丁版本的后备方案。例如,当用户安装版本 1.0.1
并且你只声明了版本 1.0.0
的 WhatsNew
时,环境将自动回退到版本 1.0.0
,并在需要时向用户呈现 WhatsNewView
。
如果你希望进一步自定义 WhatsNewEnvironment
的行为,你可以轻松地对其进行子类化并覆盖 whatsNew()
函数。
class MyCustomWhatsNewEnvironment: WhatsNewEnvironment {
/// Retrieve a WhatsNew that should be presented to the user, if available.
override func whatsNew() -> WhatsNew? {
// The current version
let currentVersion = self.currentVersion
// Your declared WhatsNew objects
let whatsNewCollection = self.whatsNewCollection
// The WhatsNewVersionStore used to determine the already presented versions
let versionStore = self.whatsNewVersionStore
// TODO: Determine WhatsNew that should be presented to the user...
}
}
WhatsNewVersionStore
是一个协议类型,负责保存和检索已呈现给用户的版本。
let whatsNewVersionStore: WhatsNewVersionStore
// Save presented versions
whatsNewVersionStore.save(presentedVersion: "1.0.0")
// Retrieve presented versions
let presentedVersions = whatsNewVersionStore.presentedVersions
// Retrieve bool value if a given version has already been presented
let hasPresented = whatsNewVersionStore.hasPresented("1.0.0")
WhatsNewKit 附带三个预定义的实现
// Persists presented versions in the UserDefaults
let userDefaultsWhatsNewVersionStore = UserDefaultsWhatsNewVersionStore()
// Persists presented versions in iCloud using the NSUbiquitousKeyValueStore
let ubiquitousKeyValueWhatsNewVersionStore = NSUbiquitousKeyValueWhatsNewVersionStore()
// Stores presented versions in memory. Perfect for testing purposes
let inMemoryWhatsNewVersionStore = InMemoryWhatsNewVersionStore()
如果你已经有一个用于存储用户相关设置的特定实现(如 Realm 或 Core Data),你可以轻松地将现有实现应用于 WhatsNewVersionStore
协议。
如果你正在使用 NSUbiquitousKeyValueWhatsNewVersionStore
,请确保在 Xcode 项目的 “Signing & Capabilities” 部分启用 iCloud 键-值存储 功能。
以下部分解释了如何初始化 WhatsNew
结构,以便描述你的应用程序给定版本的新功能。
let whatsnew = WhatsNew(
// The Version that relates to the features you want to showcase
version: "1.0.0",
// The title that is shown at the top
title: "What's New",
// The features you want to showcase
features: [
WhatsNew.Feature(
image: .init(systemName: "star.fill"),
title: "Title",
subtitle: "Subtitle"
)
],
// The primary action that is used to dismiss the WhatsNewView
primaryAction: WhatsNew.PrimaryAction(
title: "Continue",
backgroundColor: .accentColor,
foregroundColor: .white,
hapticFeedback: .notification(.success),
onDismiss: {
print("WhatsNewView has been dismissed")
}
),
// The optional secondary action that is displayed above the primary action
secondaryAction: WhatsNew.SecondaryAction(
title: "Learn more",
foregroundColor: .accentColor,
hapticFeedback: .selection,
action: .openURL(
.init(string: "https://github.com/SvenTiigi/WhatsNewKit")
)
)
)
WhatsNew.Version
指定了将某些功能引入你的应用程序的版本。
// Initialize with major, minor, and patch
let version = WhatsNew.Version(
major: 1,
minor: 0,
patch: 0
)
// Initialize by string literal
let version: WhatsNew.Version = "1.0.0"
// Initialize WhatsNew Version by using the current version of your bundle
let version: WhatsNew.Version = .current()
WhatsNew.Title
表示在功能上方呈现的标题文本。
// Initialize by string literal
let title: WhatsNew.Title = "Continue"
// Initialize with text and foreground color
let title = WhatsNew.Title(
text: "Continue",
foregroundColor: .primary
)
// On >= iOS 15 initialize with AttributedString using Markdown
let title = WhatsNew.Title(
text: try AttributedString(
markdown: "What's **New**"
)
)
WhatsNew.Feature
描述了你的应用程序的特定功能,通常由图像、标题和副标题组成。
let feature = WhatsNew.Feature(
image: .init(
systemName: "wand.and.stars"
),
title: "New Design",
subtitle: .init(
try AttributedString(
markdown: "An awesome new _Design_"
)
)
)
WhatsNew.PrimaryAction
允许你配置用于关闭呈现的 WhatsNewView
的主按钮的行为。
let primaryAction = WhatsNew.PrimaryAction(
title: "Continue",
backgroundColor: .blue,
foregroundColor: .white,
hapticFeedback: .notification(.success),
onDismiss: {
print("WhatsNewView has been dismissed")
}
)
注意:HapticFeedback 仅在 iOS 上执行
WhatsNew.SecondaryAction
显示在 WhatsNew.PrimaryAction
之上,可以在初始化 WhatsNew
实例时选择性地提供,并允许你呈现一个额外的视图、执行一个自定义操作或打开一个 URL。
// SecondaryAction that presents a View
let secondaryActionPresentAboutView = WhatsNew.SecondaryAction(
title: "Learn more",
foregroundColor: .blue,
hapticFeedback: .selection,
action: .present {
AboutView()
}
)
// SecondaryAction that opens a URL
let secondaryActionOpenURL = WhatsNew.SecondaryAction(
title: "Read more",
foregroundColor: .blue,
hapticFeedback: .selection,
action: .open(
url: .init(string: "https://github.com/SvenTiigi/WhatsNewKit")
)
)
// SecondaryAction with custom execution
let secondaryActionCustom = WhatsNew.SecondaryAction(
title: "Custom",
action: .custom { presentationMode in
// ...
}
)
注意:HapticFeedback 仅在 iOS 上执行
WhatsNewKit 允许你以各种方式调整呈现的 WhatsNewView
的布局。
最简单的方法是改变 WhatsNew.Layout.default
实例。
WhatsNew.Layout.default.featureListSpacing = 35
当使用自动呈现样式时,你可以在初始化 WhatsNewEnvironment 时提供一个默认布局。
.environment(
\.whatsNew,
.init(
defaultLayout: WhatsNew.Layout(
showsScrollViewIndicators: true,
featureListSpacing: 35
),
whatsNew: self
)
)
或者,你可以在自动或手动呈现 WhatsNewView 时传递一个 WhatsNew.Layout
。
.whatsNewSheet(
layout: WhatsNew.Layout(
contentPadding: .init(
top: 80,
leading: 0,
bottom: 0,
trailing: 0
)
)
)
.sheet(
whatsNew: self.$whatsNew,
layout: WhatsNew.Layout(
footerActionSpacing: 20
)
)
当使用 UIKit
或 AppKit
时,你可以使用 WhatsNewViewController
。
let whatsNewViewController = WhatsNewViewController(
whatsNew: WhatsNew(
version: "1.0.0",
// ...
),
layout: WhatsNew.Layout(
contentSpacing: 80
)
)
如果你希望仅在 WhatsNew 实例的版本尚未呈现时才呈现 WhatsNewViewController
,你可以使用方便的可失败的初始化程序。
// Verify WhatsNewViewController is available for presentation
guard let whatsNewViewController = WhatsNewViewController(
whatsNew: WhatsNew(
version: "1.0.0",
// ...
),
versionStore: UserDefaultsWhatsNewVersionStore()
) else {
// Version of WhatsNew has already been presented
return
}
// Present WhatsNewViewController
// Version will be automatically saved in the provided
// WhatsNewVersionStore when the WhatsNewViewController gets dismissed
self.present(whatsNewViewController, animated: true)