iOS ๐ŸŽ/Library

[SwiftUI/TipKit] ์‚ฌ์šฉ์ž์—๊ฒŒ Tip ์ œ๊ณตํ•˜๊ธฐ

fram 2023. 12. 2. 21:07

๋ณ„๋‹ค๋ฅธ ์„ค๋ช… ์—†์ด๋„ ์‚ฌ์šฉ์ž๊ฐ€ ํ•ด๋‹น UI๊ฐ€ ๋ฌด์—‡์„ ์˜๋ฏธํ•˜๋Š”์ง€, ์–ด๋–ค ๊ธฐ๋Šฅ์„ ํฌํ•จํ•˜๋Š”์ง€ ์•Œ๊ฒŒ๋” ux๊ฐ€ ๊ณ ๋ ค ๋˜๋ฉด ์ข‹๊ฒ ์ง€๋งŒ ์„ค๋ช…์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ๋„ ์žˆ์–ด์š”. ์ด ์„ค๋ช…์„ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•ด TipKit์„ ์‚ฌ์šฉํ•ด ๋ณด๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์ด๋“œ ํ”„๋กœ์ ํŠธ๋ผ minimum target iOS 17๋กœ ์„ค์ •ํ•ด ๋†“๊ณ  ํ•ด๋ณด๊ณ  ์‹ถ์€๊ฑฐ ๋‹ค ํ•ด๋ณด๊ณ  ์žˆ์–ด์š” ์•„์ด ์ข‹์•„๋ผ

 

TipKit๊ณผ ๊ฐ™์€ ToolTip์ด ํ•„์š”ํ•œ๋ฐ ๋ฒ„์ „์ด ์•ˆ๋˜์‹œ๋ฉด ์•„๋ž˜ ๊ธ€์—์„œ ํˆด ํŒ ๊ทธ๋ฆฌ๋Š” ๋ฐฉ๋ฒ• ์ฐธ๊ณ ํ•ด ๋ณด์„ธ์š”!

> 2023.11.06 - [SwiftUI] - [SwiftUI] Shape path๋กœ Tooltip ๊ทธ๋ฆฌ๊ธฐ


What is TipKit

Tipkit์€ iOS 17 ๋ถ€ํ„ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํ”„๋ ˆ์ž„์›Œํฌ๋กœ ์• ํ”Œ์ด ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์•ฑ์—์„œ ์‚ฌ์šฉ์ž์—๊ฒŒ ์„ค๋ช…์ด๋‚˜ ์•ˆ๋‚ด๋ฅผ ํ‘œ์‹œํ•˜๋Š”๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”. 


Tutorial

import TipKit

TipKit์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š”TipKit ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ž„ํฌํŠธ ํ•ด์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค. Tip ํ”„๋กœํ† ์ฝœ์„ ๋”ฐ๋ฅด๋Š” ๊ตฌ์กฐ์ฒด๊ฐ€ ํ•„์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ƒˆ๋กœ์šด ํŒŒ์ผ ํ˜น์€ Tip ๊ตฌ์กฐ์ฒด๋ฅผ ์ •์˜ํ•  ํŒŒ์ผ์— ์ž„ํฌํŠธ ํ•ด์ฃผ์„ธ์š”!

 

struct InfoTip: Tip {
    var title: Text
}

 

๊ตฌ์กฐ์ฒด ํ•˜๋‚˜๋ฅผ ๋งŒ๋“ค์–ด ์ค€๋’ค Tip ํ”„๋กœํ† ์ฝœ์„ ์ฑ„ํƒํ•ฉ๋‹ˆ๋‹ค.

Tip ํ”„๋กœํ† ์ฝœ์„ ์ž ์‹œ ์‚ดํŽด๋ณผ๊ฒŒ์š”!

@available(macOS 14.0, iOS 17.0, tvOS 17.0, watchOS 10.0, *)
public protocol Tip : Identifiable, Sendable {
    var id: String { get }
    var title: Text { get }
    var message: Text? { get }
    var image: Image? { get }
    @Tips.ActionBuilder var actions: [Self.Action] { get }
    @Tips.RuleBuilder var rules: [Self.Rule] { get }
    @Tips.OptionsBuilder var options: [TipOption] { get }
}

Tip ํ”„๋กœํ† ์ฝœ ๋‚ด๋ถ€์—๋Š” ํˆดํŒ์„ ๊ตฌํ˜„ํ•˜๋Š”๋ฐ ํ•„์š”ํ•œ ์ƒํƒœ๊ฐ’์„ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•œ ๋ณ€์ˆ˜๋“ค์ด ์ด๋ฏธ ์ •์˜๋˜์–ด ์žˆ์–ด์š”

 

struct InfoTip: Tip {
    var title: Text {
        Text("์‚ญ์ œํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ๊ธธ๊ฒŒ ๋ˆŒ๋Ÿฌ์ฃผ์„ธ์š”.")
    }
}

ํ•„์ˆ˜๋กœ title์„ ๊ตฌํ˜„ํ•ด ์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค. 

 

LazyVStack(spacing: 20) {
    ForEach(chatRooms, id: \.id) { chatRoom in
        // ์ƒ๋žต
    }
}
.padding(.bottom, 40)
.popoverTip(InfoTip()) // <- ์—ฌ๊ธฐ

 

ํˆดํŒ์„ ํ‘œํ˜„ํ•˜๊ณ  ์‹ถ์€ View์— .popoverTip modifier์„ ์‚ฌ์šฉํ•ด์„œ Tip ํ”„๋กœํ† ์ฝœ์„ ๋”ฐ๋ฅด๋Š” struct๋ฅผ ์„ ์–ธํ•ด ์ค๋‹ˆ๋‹ค.

์ด์ œ ํˆดํŒ์„ ์–ธ์ œ ๋„์šฐ๊ณ  ์‹ถ์€์ง€ ์ •ํ•ด์ค˜์•ผ ํ•ด์š”. ๊ฐ€์žฅ ์ตœ์ƒ์œ„ ๋ทฐ๋กœ ์ด๋™ํ•ด ์ฃผ์„ธ์š”.

 

import TipKit

@main
struct to_meApp: App {
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .task {
                    try? Tips.configure([
                        .displayFrequency(.immediate),
                        .datastoreLocation(.applicationDefault)
                    ])
                }
                
        }
    }
}

 

๋งˆ์ฐฌ๊ฐ€์ง€๋กœ TipKit์„ ์ž„ํฌํŠธ ํ•ด์ฃผ์„ธ์š”.

displayFrequency ์—์„œ ์ด ํˆดํŒ์„ ์–ผ๋งˆ๋‚˜ ๋…ธ์ถœ์‹œํ‚ฌ ๊ฑด์ง€ ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์–ผ๋งˆ๋‚˜ ๋…ธ์ถœ์‹œํ‚จ๋‹ค๋Š” ๋œป์ด ๋ญ”์ง€๋Š” ์—ฌ๊ธฐ ๋“ค์–ด ๊ฐˆ ์ˆ˜ ์žˆ๋Š” ๊ฐ’์„ ๋ณด๋ฉด ๋ฐ”๋กœ ๊ฐ์ด ์˜ฌ๊ฑฐ์—์š”!

์ด ํˆดํŒ์„ ๋งค์ผ ๋„์šธ๊ฑด์ง€, ๋งค ์‹œ๊ฐ„๋งˆ๋‹ค ๋„์šธ ๊ฑด์ง€, ์•„๋‹ˆ๋ฉด ํšŸ์ˆ˜ ์ œํ•œ ์—†์ด ๋„์šธ๊ฑด์ง€ ์ •ํ•  ์ˆ˜ ์žˆ์–ด์š”!

์‹คํ–‰ํ•˜๋ฉด ํ•ด๋‹น ์˜์—ญ์— ํˆดํŒ์ด ๋œจ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.