TipKit для Swift: Полное руководство по созданию подсказок пользователю
TipKit — это мощная и современная библиотека от Apple, представленная на WWDC 2023, предназначенная для создания контекстных подсказок и обучения пользователей в приложениях на SwiftUI и UIKit. Она позволяет разработчикам легко внедрять интерактивные подсказки, которые помогают пользователям быстрее освоить интерфейс, узнать о новых функциях и повысить общую вовлеченность в приложение.
Основная цель TipKit — заменить устаревшие и громоздкие решения для онбординга (например, кастомные вьюхи или сторонние библиотеки) на стандартизированный, гибкий и производительный инструмент. TipKit автоматически управляет отображением подсказок: показывает их в нужный момент, скрывает после взаимодействия, учитывает частоту показов и позволяет настраивать логику появления на основе действий пользователя или состояния приложения.
Библиотека идеально подходит для iOS 17+, macOS 14+, tvOS 17+ и watchOS 10+. Она тесно интегрируется с фреймворками Apple, поддерживает анимации, адаптивность под разные размеры экранов и работает как с SwiftUI, так и с UIKit (через UIViewRepresentable). В этой статье мы подробно разберем все возможности TipKit, от установки до сложных сценариев использования.
Установка
TipKit является частью экосистемы Apple и не требует установки через сторонние менеджеры пакетов. Для использования библиотеки достаточно добавить ее в ваш Xcode проект через стандартный Swift Package Manager (SPM) или вручную.
Через Xcode (рекомендуемый способ)
- Откройте ваш проект в Xcode.
- Выберите File → Add Package Dependencies....
- В поисковой строке введите:
https://github.com/apple/sample-tipkit.git(официальный репозиторий Apple с примерами) или используйте встроенный пакет, если он доступен в вашей версии Xcode. - Убедитесь, что выбрана ветка main или последняя стабильная версия.
- Нажмите Add Package и выберите ваш таргет.
Важно: Начиная с Xcode 15, TipKit встроен в SDK, поэтому в большинстве случаев достаточно просто импортировать модуль в коде. Если вы используете более старую версию Xcode, добавьте пакет вручную.
Через Package.swift (для SPM проектов)
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "YourProject",
dependencies: [
.package(url: "https://github.com/apple/sample-tipkit.git", from: "1.0.0")
],
targets: [
.target(
name: "YourTarget",
dependencies: ["TipKit"]
)
]
)
После добавления пакета импортируйте библиотеку в нужном файле:
import TipKit
Быстрый старт: минимальный рабочий пример
Давайте создадим простую подсказку, которая появится при первом запуске приложения и объяснит пользователю, как использовать кнопку.
import SwiftUI
import TipKit
// 1. Определяем структуру подсказки
struct WelcomeTip: Tip {
var title: Text {
Text("Добро пожаловать!")
}
var message: Text? {
Text("Нажмите эту кнопку, чтобы начать работу с приложением.")
}
var image: Image? {
Image(systemName: "hand.wave")
}
}
// 2. Используем подсказку в представлении
struct ContentView: View {
// 3. Создаем экземпляр подсказки
private let welcomeTip = WelcomeTip()
var body: some View {
VStack {
Button("Начать") {
// Действие кнопки
print("Кнопка нажата!")
}
.popoverTip(welcomeTip) // 4. Привязываем подсказку к кнопке
.padding()
}
.padding()
.task {
// 5. Конфигурируем TipKit при запуске
try? await Tips.configure()
}
}
}
// 6. Точка входа в приложение
@main
struct TipKitExampleApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
Объяснение:
- Шаг 1: Мы создали структуру
WelcomeTip, которая соответствует протоколуTip. В ней мы определили заголовок, сообщение и иконку. - Шаг 2-3: В представлении
ContentViewмы создаем экземпляр нашей подсказки. - Шаг 4: Модификатор
.popoverTip(welcomeTip)привязывает подсказку к кнопке. TipKit автоматически покажет ее при первом появлении кнопки на экране. - Шаг 5: Метод
Tips.configure()инициализирует систему подсказок. Его нужно вызвать один раз при запуске приложения (например, в.taskили вAppDelegate).
После запуска приложения вы увидите всплывающую подсказку с заголовком, текстом и иконкой. После нажатия на кнопку или вне области подсказки она исчезнет и больше не появится (если не сбросить настройки).
Основные методы, функции и классы
Рассмотрим ключевые компоненты TipKit. Для каждого элемента приведена сигнатура, описание и пример использования.
1. Протокол Tip
Сигнатура:
protocol Tip {
associatedtype Title: View
associatedtype Message: View = EmptyView
associatedtype Image: View = EmptyView
associatedtype Actions: View = EmptyView
@ViewBuilder var title: Title { get }
@ViewBuilder var message: Message? { get }
@ViewBuilder var image: Image? { get }
@ViewBuilder var actions: Actions { get }
var rules: [Rule] { get }
var options: [Option] { get }
}
Что делает: Определяет структуру подсказки. Вы обязаны реализовать свойство title, остальные свойства опциональны. Позволяет настраивать внешний вид, логику появления и действия.
Пример:
struct CustomTip: Tip {
var title: Text {
Text("Совет")
}
var message: Text? {
Text("Попробуйте провести пальцем влево, чтобы удалить элемент.")
}
var image: Image? {
Image(systemName: "hand.draw")
}
var actions: some View {
Button("Понятно") {
// Действие при нажатии на кнопку в подсказке
print("Пользователь подтвердил")
}
}
}
2. Модификатор .popoverTip(_:arrowEdge:)
Сигнатура:
func popoverTip<T: Tip>(
_ tip: T,
arrowEdge: Edge = .top
) -> some View
Что делает: Привязывает подсказку к любому View. Подсказка отображается в виде всплывающего окна (popover) с указанной стрелкой. Это основной способ отображения подсказок в SwiftUI.
Пример:
struct ButtonView: View {
let tip = MyTip()
var body: some View {
Button("Нажми меня") {
// ...
}
.popoverTip(tip, arrowEdge: .bottom)
}
}
3. Модификатор .tip(_:) для UIKit
Сигнатура (в UIKit):
// В UIKit используется через UIViewRepresentable или напрямую:
func tip(_ tip: Tip) -> UIPopoverTipView
Что делает: Позволяет отображать подсказки в UIKit приложениях. Создает UIPopoverTipView, который можно добавить к любому UIView.
Пример (через UIViewRepresentable):
struct UIKitTipView: UIViewRepresentable {
let tip: MyTip
func makeUIView(context: Context) -> UIView {
let view = UIView()
let tipView = UIPopoverTipView(tip: tip)
tipView.sourceView = view
tipView.sourceRect = view.bounds
tipView.present(animated: true)
return view
}
func updateUIView(_ uiView: UIView, context: Context) {}
}
4. Метод Tips.configure()
Сигнатура:
static func configure(options: [TipOption] = []) async throws
Что делает: Инициализирует систему TipKit. Должен быть вызван один раз перед использованием любых подсказок. Настраивает хранилище, частоту показов и другие глобальные параметры.
Пример:
// В AppDelegate или в .task
Task {
try? await Tips.configure()
// Теперь подсказки будут работать
}
5. Свойство rules в протоколе Tip
Сигнатура:
var rules: [Rule] { get }
Что делает: Позволяет задать условия, при которых подсказка будет показана. Например, показать подсказку только после того, как пользователь выполнил определенное действие.
Пример:
struct ConditionalTip: Tip {
@Parameter
static var hasTappedButton: Bool = false
var title: Text {
Text("Отличная работа!")
}
var rules: [Rule] {
#Rule(Self.$hasTappedButton) { $0 == true }
}
}
6. Макрос #Rule
Сигнатура:
#Rule<Value>(
_ parameter: Parameter<Value>,
_ condition: (Value) -> Bool
) -> Rule
Что делает: Создает правило на основе значения параметра. Позволяет динамически управлять отображением подсказки.
Пример:
#Rule(Self.$userScore) { $0 > 100 }
7. Свойство options в протоколе Tip
Сигнатура:
var options: [Option] { get }
Что делает: Позволяет настроить поведение подсказки: максимальное количество показов, интервал между показами, игнорирование и т.д.
Пример:
var options: [Option] {
// Показать максимум 3 раза, с интервалом 1 день
Tips.MaxDisplayCount(3)
Tips.DisplayFrequency(.daily)
}
8. Структура Tips.Parameter
Сигнатура:
@propertyWrapper struct Parameter<Value> where Value: Codable
Что делает: Обертка свойства, которая сохраняет состояние между запусками приложения. Используется для хранения флагов, счетчиков и других данных, влияющих на правила показа.
Пример:
struct MyTip: Tip {
@Parameter
static var appLaunchCount: Int = 0
var rules: [Rule] {
#Rule(Self.$appLaunchCount) { $0 >= 3 }
}
}
9. Метод Tips.show(_:for:) (ручной показ)
Сигнатура:
static func show(_ tip: Tip, for sourceView: UIView) throws
Что делает: Позволяет принудительно показать подсказку для указанного UIView. Используется в UIKit или когда нужно показать подсказку вне зависимости от правил.
Пример:
try? Tips.show(MyTip(), for: myButton)
10. Метод Tips.hide(_:)
Сигнатура:
static func hide(_ tip: Tip) throws
Что делает: Принудительно скрывает подсказку. Полезно, если нужно убрать подсказку при определенных условиях (например, при переходе на другой экран).
Пример:
try? Tips.hide(MyTip())
11. Структура Tips.DisplayFrequency
Сигнатура:
struct DisplayFrequency: TipOption {
enum Frequency {
case immediate
case daily
case weekly
case monthly
case custom(TimeInterval)
}
}
Что делает: Определяет, как часто подсказка может показываться одному и тому же пользователю. Позволяет избежать назойливости.
Пример:
var options: [Option] {
Tips.DisplayFrequency(.weekly)
}
12. Структура Tips.MaxDisplayCount
Сигнатура:
struct MaxDisplayCount: TipOption {
let count: Int
}
Что делает: Ограничивает