TipKit이 뭐고 꼭 필요할까?
- iOS 17부터 사용 가능한 앱을 쓰면서 새로운 기능, 숨겨진 기능, 꿀팁들을 슬쩍 알려주는 UI를 띄워주는 Framework입니다.
- 아래와 같이 리스트를 꾹 눌러서 순서를 조정할 수 있는 건 보통 알기 힘든 경우가 많기 때문에 슬쩍 알려주는 형식입니다.
- 물론 이걸 직접 구현할 수도 있습니다. Tooltip 정도는 간단한 UI이니 공수도 그렇게 많이 들지 않겠죠? 하지만 Tipkit에서는 저 Tip 언제 어떤 조건으로 보여줘야 하는지, 너무 많은 팁이 노출되면 유저가 피로하니 너무 많이 노출되지 않게 조절하는 등의 편리한 추가 기능이 있어서 굳이 안 쓸 이유는 없습니다.
너무 과하게 쓰면 안 됨! 😵
애플의 Human Interface Guideline을 보면 Tipkit의 역할과 주의해야 할 점들을 알 수 있습니다.
한 마디로 여기에는 짧은 꿀팁만 넣어! 입니다. 너무 긴 정보나 팁이 아닌 경고 문구 등은 넣지 말고 빠르게 읽고 쉽게 이해할 수 있는 정보들을 넣어서 유저에게 가치를 주라는 의도입니다. (Quick, Instructional, Easy to Understand)
Tipkit의 전체적인 구조
🐜 Tip 정의하기
우선 Tip이라는 Protocol이 있습니다. 여기서 Tip에서 보여 줄 정보의 title, message, image와 언제 tip을 보여줄 것인지에 대한 규칙 (rules)를 정의합니다.
struct ExampleTip: Tip {
var title: Text {}
var message: Text? {}
var image: Image? {}
var rules: [Rule] {}
}
🐜 Tips로 여러 설정하기
이런 팁들을 여러개 정의하면 이걸 어떻게 보여줄 것인지 설정할 수 있는 Tips 객체가 있습니다. 여기서...
- Tip을 어느 주기로 보여 줄 것인지 (계속, 매일, 매주, 매월 등)
- Tip을 보여주기 위한 조건의 달성 여부나 언제 보여줬음 등의 정보를 어디에 저장할 것인지
등을 설정합니다.
try? Tips.configure([
.displayFrequency(.immediate),
.datastoreLocation(.applicationDefault)
])
🐜 UI에서 Tip 보여줄 부분에 추가하기
그러면 이제 UI의 어떤 부분에 Tip을 보여줄 것인지 설정할 수 있습니다. 크게 .popoverTip()과 TipView가 있는데 이는 밑에서 자세히 설명해 드리겠습니다.
🐜 유저가 원하는 동작을 하면 Tip에 이벤트로 알려주기
이제 Tip이 어떻게 생겼고 언제 보여줄지, 어디에 보여줄지, 어느 정도 주기로 보여줄지는 정의가 끝났으니 실제 앱에서 특정 행동을 했을 때 이벤트를 기부해서 (donate)해서 Tip Protocol이 규칙으로 Tip을 보여줄지 말지 판단할 수 있게 해야 합니다.
뭔 말이냐 하면, 유저가 이미 특정 기능을 잘 쓰고 있는데 그걸 팁으로 알려 줄 필요는 없으니 (오히려 앱을 쓰는데 방해될 테니) 이런 동작을 하면 팁을 안 보여주게 해야 합니다. 또, 유저가 특정 기능을 많이 쓰지도 않는데 그거에 관한 팁을 알려 줄 필요는 없으니 많이 쓸 때만 알려줄 수 있도록 특정 기능을 쓸 때마다 이벤트를 기부해서 이걸 몇 번 이상 한 경우에만 팁을 보여주자!라는 식으로 설정할 수 있게 해야 합니다.
TipKit 사용법
사용법을 익히는데는 직접 해 보는 게 최고라고 생각합니다. 그래서 제 앱에서 실제 TipKit을 어떻게 썼는지 예제와 함께 알려 드리겠습니다.
저는 일단 Swipe해서 수정 삭제가 가능한데 이걸 모르는 유저도 있을 거 같아 이걸 TipKit으로 보여주기로 했습니다.
위에서 말씀 드렸다 싶이 사실 수정/삭제를 많이 안 하시는 분들이나 이미 Swipe로 수정 삭제를 하는 분들에게 굳이 이 Tip을 보여 줄 필요는 없기 때문에 2가지 규칙을 정했습니다.
- Swipe 해서 수정/삭제를 1번도 사용한 적 없어야 함
- Detail에 들어가서 번거롭게 수정/삭제를 3번 이상 해야 함
그럼 Tip Protocol 정의부터 시작해 보겠습니다.
import TipKit
struct SwipeToDeleteTip: Tip {
static let editOrDeleteFromDetailViewEvent = Event(id: "editOrDeleteInDetailView")
var title: Text {
Text("왼쪽으로 밀어서 간편하게 수정/삭제할 수 있어요.")
}
var image: Image? {
Image(systemName: "trash.circle.fill")
}
var rules: [Rule] {
// 상세 페이지에서 수정 삭제를 3번 이상 해야 함
#Rule(Self.editOrDeleteFromDetailViewEvent) { event in
event.donations.count >= 3
}
}
}
- Swipe 해서 수정/삭제 이벤트를 추가해 유저가 해당 동작을 할 때마다 기록할 예정입니다.
- title과 image는 부드러운 말투와 도움이 되는 이미지로 간단히 만들었고,
- 2번째 규칙을 rules에 구현했습니다. 1번째 규칙은 1번만 해도 끝이기 때문에 따로 기록하지 않고 바로. invalidate()를 써서 Tip을 없앨 생각입니다.
이제 이 Tip을 어디 UI에서 보여줄지 설정해야 합니다. 간단히 2종류만 추가하겠습니다.
// 리스트의 맨 위에 보여줌
List {
TipView(SwipeToDeleteTip())
ForEach(expenses) { expense in
ExpenseListRow(expense)
}
}
// Tooltip 형태도 추가
List {
ForEach(creditCards) { creditCard in
CreditCardListRow(creditCard)
.popoverTip(SwipeToDeleteTip())
}
}
다음으로 이벤트가 발생하는 모든 곳에서 알려 줘야 합니다. 우선 Swipe 해서 수정 삭제를 하는 모든 곳에서. invalidate()를 호출해 Tip을 안 보여 주도록 처리하겠습니다.
private func performSwipeToEdit() {
SwipeToDeleteTip().invalidate(reason: .actionPerformed)
// 나머지 수정하는 코드
}
private func performSwipeToDelete() {
SwipeToDeleteTip().invalidate(reason: .actionPerformed)
// 나머지 삭제하는 코드
}
그리고 상세 페이지에 가서 번거롭게 수정/삭제를 한 경우는 Event를 donate 하겠습니다.
private func performEdit() {
Task {
await SwipeToDeleteTip.editOrDeleteFromDetailViewEvent.donate()
}
// 나머지 수정하는 코드
}
private func performDelte() {
Task {
await SwipeToDelteTip.editOrDeleteFromDetailViewEvent.donate()
}
// 나머지 삭제하는 코드
}
마지막으로 앱이 열릴 때마다 Tip을 세팅하겠습니다.
private func setupTips() {
try? Tips.configure([
.displayFrequency(.daily),
.datastoreLocation(.applicationDefault)
])
}
참고
'👨💻 프로그래밍 > 🍎 iOS 개발' 카테고리의 다른 글
🍎 Stanford iOS 강의 (CS193P) 수강 후기 (6) | 2024.09.14 |
---|---|
🍎 Swift의 mutating 알아보기 (feat. Cannot assign to property: 'self' is immutable) (0) | 2024.09.01 |
🍎 Swift Testing: 보기 싫은 XCTest는 이제 안녕!! (0) | 2024.08.15 |
🍎 Swift Package에서 Localization 처리하기 (0) | 2024.08.10 |
🍎 나만의 Swift Package 만들기! - 개인 프로젝트에서 중복되는 코드 없애기 (0) | 2024.08.08 |