介紹
一言以蔽之:TipKit 是一種顯示提示信息的新框架前普。
使用步驟
- 導(dǎo)入模塊
import TipKit
。 - 創(chuàng)建遵守
Tip
協(xié)議的結(jié)構(gòu)體 Tip,配置提示信息內(nèi)容景殷。 - 通過
TipUIView
或者TipUIPopoverViewController
顯示創(chuàng)建的 Tip。 - App 啟動時通過
Tips.configure()
初始化 Tip 系統(tǒng)澡屡,并且可以配置顯示頻率猿挚、數(shù)據(jù)存儲位置等內(nèi)容。
實現(xiàn)
AppDelegate
import UIKit
// 導(dǎo)入TipKit
import TipKit
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// 初始化Tip System
try? Tips.configure([
// 顯示頻率
.displayFrequency(.daily),
// 數(shù)據(jù)存儲位置
.datastoreLocation(.applicationDefault)
])
return true
}
}
Tip Struct
import TipKit
import UIKit
// MARK: - 自定義Tip
struct SearchTip: Tip {
// 標(biāo)題
var title: Text {
Text("搜索提示")
}
// 消息
var message: Text? {
Text("點擊這里可以進(jìn)行搜索")
}
// 圖片
var image: Image? {
Image(systemName: "globe")
}
// 按鈕
var actions: [Action] {
[
Action(id: "id_more", title: "更多") {
print("點擊更多")
},
Action(id: "id_dismiss", title: "關(guān)閉"),
// Action(id: "id_dismiss", title: "關(guān)閉", disabled: true)
]
}
// 顯示規(guī)則
// 1. 基于參數(shù)規(guī)則
@Parameter
static var showTip: Bool = false
// 2. 基于事件規(guī)則
static let appOpenedCount = Event(id: "appOpenedCount")
var rules: [Rule] {
[
#Rule(Self.$showTip) { $0 == true }, // showTip為true
#Rule(Self.appOpenedCount) { $0.donations.count >= 3 } // 打開超過3次
]
}
// 選項
var options: [TipOption] {
[
Tip.IgnoresDisplayFrequency(true), // 忽略顯示頻率限制即立即顯示
Tip.MaxDisplayCount(3) // 最大顯示次數(shù)
]
}
}
// MARK: - 自定義簡單Tip
struct OperationTip: Tip {
var title: Text {
Text("操作提示")
.foregroundStyle(.red)
.font(.title2)
.fontDesign(.serif)
.bold()
}
var message: Text? {
Text("通過觸摸屏幕顯示TipKit")
.foregroundStyle(.white)
.font(.title3)
.fontDesign(.monospaced)
}
var image: Image? {
Image(systemName: "info.bubble")
}
}
View Controller
import TipKit
import UIKit
class ViewController: UIViewController {
lazy var button: UIButton = {
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 30))
button.setTitle("顯示Tip", for: .normal)
button.center = view.center
button.addTarget(self, action: #selector(showTip), for: .touchUpInside)
return button
}()
// TipUIPopoverViewController
var tipUIPopoverViewController: TipUIPopoverViewController?
// TipUIView
lazy var tipUIView: TipUIView = {
let tipUIView = TipUIView(operationTip, arrowEdge: .bottom)
tipUIView.backgroundColor = .black
tipUIView.tintColor = .red
tipUIView.cornerRadius = 6.0
tipUIView.imageSize = CGSize(width: 40, height: 40)
tipUIView.translatesAutoresizingMaskIntoConstraints = false
return tipUIView
}()
// Tip
var searchTip = SearchTip()
var operationTip = OperationTip()
var searchTipObservationTask: Task<Void, Never>?
var operationTipObservationTask: Task<Void, Never>?
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
view.backgroundColor = .systemTeal
view.addSubview(button)
Task {
await SearchTip.appOpenedCount.donate()
}
}
@objc func showTip() {
SearchTip.showTip = true
// 顯隱TipUIPopoverViewController
searchTipObservationTask = searchTipObservationTask ?? Task { @MainActor in
for await shouldDisplay in searchTip.shouldDisplayUpdates {
if shouldDisplay {
tipUIPopoverViewController = TipUIPopoverViewController(searchTip, sourceItem: button)
present(tipUIPopoverViewController!, animated: true)
} else {
tipUIPopoverViewController?.dismiss(animated: true, completion: nil)
}
}
}
// 顯隱TipUIView
operationTipObservationTask = operationTipObservationTask ?? Task { @MainActor in
for await shouldDisplay in operationTip.shouldDisplayUpdates {
if shouldDisplay {
view.addSubview(tipUIView)
NSLayoutConstraint.activate([
tipUIView.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: -100),
tipUIView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20.0),
tipUIView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20.0)
])
} else {
tipUIView.removeFromSuperview()
}
}
}
}
}
效果
- 運(yùn)行后直接點擊按鈕驶鹉。
效果一
- 運(yùn)行 3 次后再次點擊按鈕绩蜻。
效果二