<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>TipKit » MszPro・株式会社Smartソフト</title>
	<atom:link href="https://mszpro.com/category/tipkit/feed" rel="self" type="application/rss+xml" />
	<link>https://mszpro.com</link>
	<description>iOS VisionOS SwiftUI Programming Blog. Dream it, Chase it, Code it.</description>
	<lastBuildDate>Tue, 17 Dec 2024 04:47:49 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8.1</generator>

<image>
	<url>https://static-assets.mszpro.com/2024/12/cropped-Unknown-32x32.webp</url>
	<title>TipKit » MszPro・株式会社Smartソフト</title>
	<link>https://mszpro.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>SwiftUIでTipKitを使用してユーザーにヒントを表示（iOS 17、WWDC 2023）</title>
		<link>https://mszpro.com/tipkit-ios17-ja</link>
		
		<dc:creator><![CDATA[msz]]></dc:creator>
		<pubDate>Mon, 16 Dec 2024 07:28:13 +0000</pubDate>
				<category><![CDATA[SwiftUI]]></category>
		<category><![CDATA[TipKit]]></category>
		<guid isPermaLink="false">https://mszpro.com/?p=304</guid>

					<description><![CDATA[<p>TipKitフレームワークを使用して、アプリ内のさまざまな機能をユーザーに発見させる方法。インラインヒントやフローティングヒントの表示、条件やカウンターに基づくヒントの活用、さらにヒントのアクションボタンのカスタマイズについて説明します。</p>
<p>The post <a href="https://mszpro.com/tipkit-ios17-ja">SwiftUIでTipKitを使用してユーザーにヒントを表示（iOS 17、WWDC 2023）</a> first appeared on <a href="https://mszpro.com">MszPro・株式会社Smartソフト</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>この記事では、iOS 17の新しいTipKitフレームワークを使用して、アプリ内のさまざまな機能をユーザーに発見させる方法について説明します。</p>



<figure class="wp-block-image"><a href="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F635330%2F5c1f1923-ba2d-31e2-6a2c-a5ec76bd1494.jpeg?ixlib=rb-4.0.0&amp;auto=format&amp;gif-q=60&amp;q=75&amp;s=9df042b23d03dddc92144fc456c70410" target="_blank" rel="noreferrer noopener"><img fetchpriority="high" decoding="async" width="1290" height="682" src="https://static-assets.mszpro.com/2024/12/https3A2F2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com2F02F6353302F5c1f1923-ba2d-31e2-6a2c-a5ec76bd1494.jpg" alt="tipkit-inline-2.jpg" class="wp-image-307" srcset="https://static-assets.mszpro.com/2024/12/https3A2F2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com2F02F6353302F5c1f1923-ba2d-31e2-6a2c-a5ec76bd1494-300x159.jpg 300w, https://static-assets.mszpro.com/2024/12/https3A2F2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com2F02F6353302F5c1f1923-ba2d-31e2-6a2c-a5ec76bd1494-1024x541.jpg 1024w, https://static-assets.mszpro.com/2024/12/https3A2F2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com2F02F6353302F5c1f1923-ba2d-31e2-6a2c-a5ec76bd1494-768x406.jpg 768w, https://static-assets.mszpro.com/2024/12/https3A2F2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com2F02F6353302F5c1f1923-ba2d-31e2-6a2c-a5ec76bd1494.jpg 1290w" sizes="(max-width: 1290px) 100vw, 1290px" /></a></figure>



<p>本記事の内容は以下の通りです：</p>



<ul class="wp-block-list">
<li>インラインヒントの表示</li>



<li>フローティングヒントの表示</li>



<li>条件に基づくヒントの表示</li>



<li>カウンターに基づくヒントの表示</li>



<li>ヒントのアクションボタンのカスタマイズ</li>
</ul>



<p>この記事は、主にSwiftUIを対象としています。</p>



<h2 class="wp-block-heading"><a href="https://qiita.com/mashunzhe/items/016e991fb9020b3eb4c7#tip%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AE%E5%AE%9A%E7%BE%A9"></a>Tipオブジェクトの定義</h2>



<p>Tipオブジェクトには、画像、タイトル、説明、およびヒントのアクションが含まれています。以下はシンプルなヒントの例です：</p>



<p><code>var asset: Image?</code>&nbsp;には、ヒントの左側に表示するオプションの画像を提供できます。<br><code>var title: Text</code>&nbsp;には、このヒントのタイトルとして表示したいSwiftUIのテキストを提供します。<br><code>var message: Text?</code>&nbsp;には、タイトルの下部に表示されるオプションの説明文字列を提供できます。</p>



<pre class="wp-block-code"><code>import TipKit

struct HashTagPostButtonTip: Tip {
    var image: Image? {
        Image(systemName: "star.bubble")
    }
    var title: Text {
        Text("Send a Quick Response")
    }
    var message: Text? {
        Text("Double-tap a message, then choose a Tapback, like a ♥︎.")
    }
}
</code></pre>



<figure class="wp-block-image"><a href="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F635330%2Fc30a3b45-5798-7d39-8da3-afc2e7a139b1.jpeg?ixlib=rb-4.0.0&amp;auto=format&amp;gif-q=60&amp;q=75&amp;s=c520fd07d629588424135f6c14bd06c6" target="_blank" rel="noreferrer noopener"><img decoding="async" width="1290" height="790" src="https://static-assets.mszpro.com/2024/12/https3A2F2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com2F02F6353302Fc30a3b45-5798-7d39-8da3-afc2e7a139b1.jpg" alt="tipkit-floating.jpg" class="wp-image-312" srcset="https://static-assets.mszpro.com/2024/12/https3A2F2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com2F02F6353302Fc30a3b45-5798-7d39-8da3-afc2e7a139b1-300x184.jpg 300w, https://static-assets.mszpro.com/2024/12/https3A2F2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com2F02F6353302Fc30a3b45-5798-7d39-8da3-afc2e7a139b1-1024x627.jpg 1024w, https://static-assets.mszpro.com/2024/12/https3A2F2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com2F02F6353302Fc30a3b45-5798-7d39-8da3-afc2e7a139b1-768x470.jpg 768w, https://static-assets.mszpro.com/2024/12/https3A2F2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com2F02F6353302Fc30a3b45-5798-7d39-8da3-afc2e7a139b1.jpg 1290w" sizes="(max-width: 1290px) 100vw, 1290px" /></a></figure>



<p>また、<code>var rules: [Rule]</code>&nbsp;および&nbsp;<code>var actions: [Action]</code>&nbsp;パラメータもありますが、これについては記事の次のセクションで説明します。</p>



<h2 class="wp-block-heading"><a href="https://qiita.com/mashunzhe/items/016e991fb9020b3eb4c7#%E3%83%92%E3%83%B3%E3%83%88%E3%81%AE%E8%A1%A8%E7%A4%BA"></a>ヒントの表示</h2>



<p>ヒントを表示する方法は2つあります。</p>



<figure class="wp-block-image"><a href="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F635330%2Fef3cc4e1-e19b-bd34-1133-0c77c0c65da0.jpeg?ixlib=rb-4.0.0&amp;auto=format&amp;gif-q=60&amp;q=75&amp;s=6f6ebb6e41fb99ba752cf38d6bdd008b" target="_blank" rel="noreferrer noopener"><img decoding="async" width="720" height="561" src="https://static-assets.mszpro.com/2024/12/https3A2F2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com2F02F6353302Fef3cc4e1-e19b-bd34-1133-0c77c0c65da0.jpg" alt="apple-tip-view-ways.jpeg" class="wp-image-311" srcset="https://static-assets.mszpro.com/2024/12/https3A2F2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com2F02F6353302Fef3cc4e1-e19b-bd34-1133-0c77c0c65da0-300x234.jpg 300w, https://static-assets.mszpro.com/2024/12/https3A2F2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com2F02F6353302Fef3cc4e1-e19b-bd34-1133-0c77c0c65da0.jpg 720w" sizes="(max-width: 720px) 100vw, 720px" /></a></figure>



<p>(from WWDC video)</p>



<h3 class="wp-block-heading"><a href="https://qiita.com/mashunzhe/items/016e991fb9020b3eb4c7#%E3%82%A4%E3%83%B3%E3%83%A9%E3%82%A4%E3%83%B3%E3%83%92%E3%83%B3%E3%83%88"></a>インラインヒント</h3>



<p>ヒントをビュー内に表示することができます。ヒントビューは、あなたの機能（例：ボタン）を指す矢印とともに表示されます。これは、TipViewをビューコードに直接含めることで実現できます：</p>



<figure class="wp-block-image"><a href="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F635330%2F5c1f1923-ba2d-31e2-6a2c-a5ec76bd1494.jpeg?ixlib=rb-4.0.0&amp;auto=format&amp;gif-q=60&amp;q=75&amp;s=9df042b23d03dddc92144fc456c70410" target="_blank" rel="noreferrer noopener"><img fetchpriority="high" decoding="async" width="1290" height="682" src="https://static-assets.mszpro.com/2024/12/https3A2F2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com2F02F6353302F5c1f1923-ba2d-31e2-6a2c-a5ec76bd1494.jpg" alt="tipkit-inline-2.jpg" class="wp-image-307" srcset="https://static-assets.mszpro.com/2024/12/https3A2F2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com2F02F6353302F5c1f1923-ba2d-31e2-6a2c-a5ec76bd1494-300x159.jpg 300w, https://static-assets.mszpro.com/2024/12/https3A2F2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com2F02F6353302F5c1f1923-ba2d-31e2-6a2c-a5ec76bd1494-1024x541.jpg 1024w, https://static-assets.mszpro.com/2024/12/https3A2F2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com2F02F6353302F5c1f1923-ba2d-31e2-6a2c-a5ec76bd1494-768x406.jpg 768w, https://static-assets.mszpro.com/2024/12/https3A2F2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com2F02F6353302F5c1f1923-ba2d-31e2-6a2c-a5ec76bd1494.jpg 1290w" sizes="(max-width: 1290px) 100vw, 1290px" /></a></figure>



<pre class="wp-block-code"><code>import SwiftUI
import TipKit

struct TipWithArrow: View {
    var body: some View {
        VStack {
            
            HStack {
                TipView(HashTagPostButtonTip(), arrowEdge: .trailing)
                
                Image(systemName: "number")
                    .font(.system(size: 30))
                    .foregroundStyle(.white)
                    .padding()
                    .background { Circle().foregroundStyle(.blue) }
            }
            
        }
        .padding()
        .task {
            try? Tips.configure(&#91;
                .displayFrequency(.immediate),
                .datastoreLocation(.applicationDefault)
            ])
        }
    }
}

#Preview {
    TipWithArrow()
}
</code></pre>



<p><code>arrowEdge</code>&nbsp;パラメータを使用して、矢印の指す方向を決定することができます。<br><code>.trailing</code>&nbsp;に設定すると、ヒントは右側を指す矢印を表示します（つまり、機能ボタンが右側にあります）。<br>また、機能ボタンが左側にあり（表示されているヒントがボタンの右側にある場合）、<code>.leading</code>に設定します。</p>



<h3 class="wp-block-heading"><a href="https://qiita.com/mashunzhe/items/016e991fb9020b3eb4c7#%E3%83%95%E3%83%AD%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%E3%83%9D%E3%83%83%E3%83%97%E3%82%AA%E3%83%BC%E3%83%90%E3%83%BC%E3%83%92%E3%83%B3%E3%83%88"></a>フローティング（ポップオーバー）ヒント</h3>



<p>ボタンにフローティングヒントを添付するためのビューモディファイアも使用できます。これは、例えばナビゲーションボタンに対するヒントを表示したい場合に便利です：</p>



<figure class="wp-block-image"><a href="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F635330%2Fd8555fc2-166b-6750-4c46-979233271321.jpeg?ixlib=rb-4.0.0&amp;auto=format&amp;gif-q=60&amp;q=75&amp;s=e75e657a366bdce5c4268a4123d3690c" target="_blank" rel="noreferrer noopener"><img loading="lazy" decoding="async" width="1290" height="740" src="https://static-assets.mszpro.com/2024/12/https3A2F2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com2F02F6353302Fd8555fc2-166b-6750-4c46-979233271321.jpg" alt="floating-tip.jpg" class="wp-image-309" srcset="https://static-assets.mszpro.com/2024/12/https3A2F2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com2F02F6353302Fd8555fc2-166b-6750-4c46-979233271321-300x172.jpg 300w, https://static-assets.mszpro.com/2024/12/https3A2F2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com2F02F6353302Fd8555fc2-166b-6750-4c46-979233271321-1024x587.jpg 1024w, https://static-assets.mszpro.com/2024/12/https3A2F2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com2F02F6353302Fd8555fc2-166b-6750-4c46-979233271321-768x441.jpg 768w, https://static-assets.mszpro.com/2024/12/https3A2F2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com2F02F6353302Fd8555fc2-166b-6750-4c46-979233271321.jpg 1290w" sizes="auto, (max-width: 1290px) 100vw, 1290px" /></a></figure>



<pre class="wp-block-code"><code>struct PopOverTip: View {
    
    var hashtagButtonTip = HashTagPostButtonTip()
    
    var body: some View {
        VStack {
            
            Text("Hello world!")
            
        }
        .padding()
        .toolbar {
            ToolbarItem(placement: .navigationBarTrailing) {
                Image(systemName: "number")
                    .onTapGesture {
                        hashtagButtonTip.invalidate(reason: .actionPerformed)
                    }
                    .popoverTip(hashtagButtonTip)
            }
        }
        .task {
            try? Tips.configure(&#91;
                .displayFrequency(.immediate),
                .datastoreLocation(.applicationDefault)
            ])
        }
    }
    
}

#Preview {
    PopOverTip()
}

</code></pre>



<p>If you want your app to be compatible also with previous iOS versions, you can use a similar technique as shown below to create a conditional view modifier:</p>



<pre class="wp-block-code"><code>extension View {
	@ViewBuilder
	func tipIfAvailable(with tip: Tip) -&gt; some View {
		if #available(iOS 17, *) {
			self
				.popoverTip(tip)
		}
	}
}
</code></pre>



<h2 class="wp-block-heading"><a href="https://qiita.com/mashunzhe/items/016e991fb9020b3eb4c7#%E3%83%92%E3%83%B3%E3%83%88%E3%81%AE%E9%A0%BB%E5%BA%A6"></a>ヒントの頻度</h2>



<p>デフォルトでは、各ヒントは一度だけ表示されます。<br><code>.displayFrequency(.immediate)</code>&nbsp;に設定すると、ユーザーが以前にヒントを見ていない場合、ヒントはすぐに表示されます。<br>他の表示頻度も設定することができます。例えば、<code>.hourly</code>&nbsp;に設定すると、システムは1時間に1回以上ヒントが表示されないようにします。<br>ヒントデータの保存場所（ヒントが表示されたかどうか）も&nbsp;<code>.datastoreLocation(.applicationDefault)</code>&nbsp;関数を使用してカスタマイズできます。</p>



<h2 class="wp-block-heading"><a href="https://qiita.com/mashunzhe/items/016e991fb9020b3eb4c7#%E7%89%B9%E5%AE%9A%E3%81%AE%E6%9D%A1%E4%BB%B6%E3%81%8C%E6%BA%80%E3%81%9F%E3%81%95%E3%82%8C%E3%81%9F%E3%81%A8%E3%81%8D%E3%81%AB%E3%83%92%E3%83%B3%E3%83%88%E3%82%92%E8%A1%A8%E7%A4%BA"></a>特定の条件が満たされたときにヒントを表示</h2>



<p>特定の条件が満たされた場合にのみヒントを表示することができます。例えば、プレミアム機能のヒントは、ユーザーがプレミアム機能を購入した場合にのみ表示されるべきです。<br>Tipオブジェクトの静的変数を定義することができます。その後、その静的変数に値を割り当てることで、ヒントが表示されるかどうかを制御することができます。</p>



<pre class="wp-block-code"><code>import TipKit

struct PremiumUserOnlyTip: Tip {
    
    @Parameter
    static var isPremiumUser: Bool = false
    
    var image: Image? {
        Image(systemName: "wand.and.rays")
    }
    var title: Text {
        Text("Add an Effect")
    }
    var message: Text? {
        Text("Choose a fun Live Photo effect like Loop or Bounce.")
    }
    
    var rules: &#91;Rule] {
        #Rule(Self.$isPremiumUser) {
            $0 == true
        }
    }
    
}

</code></pre>



<p>アプリの起動時に、静的変数&nbsp;<code>PremiumUserOnlyTip.isPremiumUser</code>&nbsp;を設定することで、ヒントはプレミアムユーザーのみに表示されます。</p>



<h2 class="wp-block-heading"><a href="https://qiita.com/mashunzhe/items/016e991fb9020b3eb4c7#%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%A9%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E8%A8%98%E9%8C%B2%E3%81%97%E3%81%9D%E3%82%8C%E3%81%AB%E5%BF%9C%E3%81%98%E3%81%A6%E3%83%92%E3%83%B3%E3%83%88%E3%82%92%E8%A1%A8%E7%A4%BA"></a>ユーザーのインタラクションを記録し、それに応じてヒントを表示</h2>



<p>ユーザーのインタラクションをカウンターとして記録（アプリを使用した回数など）し、ユーザーが要件を満たしたときのみヒントを表示することができます。</p>



<pre class="wp-block-code"><code>import TipKit

struct UsageFrequencyBasedTip: Tip {
    
    static let numerOfTimesOpened: Event = Event(id: "com.example.TipKit.numberOfTimesOpened")
    
    var image: Image? {
        Image(systemName: "star.fill")
    }
    var title: Text {
        Text("Tap to download HD picture")
    }
    var message: Text? {
        Text("Only for premium users")
    }
    
    var rules: &#91;Rule] {
        #Rule(Self.numerOfTimesOpened) {
            $0.donations.count &gt;= 3
        }
    }
    
}
</code></pre>



<p>上記のコードでは、Eventオブジェクトを使用してアプリを開いた回数を記録します。rulesパラメータでは、Swiftのマクロを使用して、ユーザーがアプリを開いた回数が3回以上の場合にのみヒントが表示されることを示しています。<br>これで、アプリ内で以下のコードを使用してカウンターをインクリメントできます：</p>



<pre class="wp-block-code"><code>Button("tap this button 3 times") {
    Task {
        await UsageFrequencyBasedTip.numerOfTimesOpened.donate()
    }
}
</code></pre>



<p><code>UsageFrequencyBasedTip.numerOfTimesOpened.donate()</code>&nbsp;関数を3回呼び出すと、ヒントが表示されます</p>



<h2 class="wp-block-heading"><a href="https://qiita.com/mashunzhe/items/016e991fb9020b3eb4c7#%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0%E3%82%A2%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E4%BB%98%E3%81%8D%E3%83%92%E3%83%B3%E3%83%88"></a>カスタムアクション付きヒント</h2>



<p>ヒントのアクションボタンを提供することもできます：</p>



<figure class="wp-block-image"><a href="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F635330%2F7aa44441-98ff-1329-2ba5-0b6a8f7d7024.jpeg?ixlib=rb-4.0.0&amp;auto=format&amp;gif-q=60&amp;q=75&amp;s=a4ced2b6aa2c257d8c019a17ba123a96" target="_blank" rel="noreferrer noopener"><img loading="lazy" decoding="async" width="1290" height="701" src="https://static-assets.mszpro.com/2024/12/https3A2F2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com2F02F6353302F7aa44441-98ff-1329-2ba5-0b6a8f7d7024.jpg" alt="tip-custom-actions.jpg" class="wp-image-310" srcset="https://static-assets.mszpro.com/2024/12/https3A2F2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com2F02F6353302F7aa44441-98ff-1329-2ba5-0b6a8f7d7024-300x163.jpg 300w, https://static-assets.mszpro.com/2024/12/https3A2F2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com2F02F6353302F7aa44441-98ff-1329-2ba5-0b6a8f7d7024-1024x556.jpg 1024w, https://static-assets.mszpro.com/2024/12/https3A2F2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com2F02F6353302F7aa44441-98ff-1329-2ba5-0b6a8f7d7024-768x417.jpg 768w, https://static-assets.mszpro.com/2024/12/https3A2F2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com2F02F6353302F7aa44441-98ff-1329-2ba5-0b6a8f7d7024.jpg 1290w" sizes="auto, (max-width: 1290px) 100vw, 1290px" /></a></figure>



<pre class="wp-block-code"><code>import TipKit

struct TipWithOptions: Tip {
    
    var image: Image? {
        Image(systemName: "star.bubble")
    }
    
    var title: Text {
        Text("Send a Quick Response")
    }
    
    var message: Text? {
        Text("Double-tap a message, then choose a Tapback, like a ♥︎.")
    }
    
    var actions: &#91;Action] {
        return &#91;
            .init(id: "learn-more", title: "Learn more", perform: {
                print("Learn more tapped")
            }),
            .init(id: "enable-feature", title: "Enable magic feature", perform: {
                print("Enable feature tapped")
            })
        ]
    }
    
}</code></pre>



<h2 class="wp-block-heading"><a href="https://qiita.com/mashunzhe/items/016e991fb9020b3eb4c7#%E3%83%92%E3%83%B3%E3%83%88%E3%81%AE%E3%83%87%E3%83%90%E3%83%83%E3%82%B0"></a>ヒントのデバッグ</h2>



<p>以下の関数を使用して、ヒントをデバッグすることができます：<br>ヒントが表示されたかどうかのストレージデータベースをリセット：</p>



<pre class="wp-block-code"><code>try? Tips.resetDatastore()</code></pre>



<p>上記のコードは、Tips/configure(options:)を呼び出す前に呼び出す必要があります。<br>ヒントが以前に表示されたかどうかに関係なく、すべてのヒントを表示することもできます：</p>



<pre class="wp-block-code"><code>Tips.showAllTipsForTesting()</code></pre>



<p>ヒントが以前に表示されたかどうかに関係なく、特定のヒントを表示する：</p>



<pre class="wp-block-code"><code>Tips.showTipsForTesting(&#91;ExampleTip.self])</code></pre>



<p>パラメータで、ヒントのタイプの配列を提供します。<br>すべてのヒントを隠す、または特定のタイプのヒントのみを隠すこともできます：</p>



<pre class="wp-block-code"><code>Tips.hideAllTipsForTesting()
Tips.hideTipsForTesting(_ tips: &#91;Tip.Type])</code></pre>



<h2 class="wp-block-heading"><a href="https://qiita.com/mashunzhe/items/016e991fb9020b3eb4c7#%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%82%B3%E3%83%BC%E3%83%89"></a>サンプルコード</h2>



<p>iOS 17が公開された後、サンプルのXcodeプロジェクトをアップロードします。</p>



<h2 class="wp-block-heading"><a href="https://qiita.com/mashunzhe/items/016e991fb9020b3eb4c7#good--ng"></a>Good &amp; NG</h2>



<figure class="wp-block-image"><a href="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F635330%2F3b07be64-5fbb-09b5-0026-6a9d368c4885.jpeg?ixlib=rb-4.0.0&amp;auto=format&amp;gif-q=60&amp;q=75&amp;s=f27eda4ef87c27edbf4c6a6f41824d92" target="_blank" rel="noreferrer noopener"><img loading="lazy" decoding="async" width="720" height="402" src="https://static-assets.mszpro.com/2024/12/https3A2F2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com2F02F6353302F3b07be64-5fbb-09b5-0026-6a9d368c4885.jpg" alt="tipkit-good.jpeg" class="wp-image-308" srcset="https://static-assets.mszpro.com/2024/12/https3A2F2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com2F02F6353302F3b07be64-5fbb-09b5-0026-6a9d368c4885-300x168.jpg 300w, https://static-assets.mszpro.com/2024/12/https3A2F2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com2F02F6353302F3b07be64-5fbb-09b5-0026-6a9d368c4885.jpg 720w" sizes="auto, (max-width: 720px) 100vw, 720px" /></a></figure>



<figure class="wp-block-image"><a href="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F635330%2Fd02dcdd1-1dc7-068e-0d90-5b04f9065a60.jpeg?ixlib=rb-4.0.0&amp;auto=format&amp;gif-q=60&amp;q=75&amp;s=626639c880aa5845456c353b2cec0b40" target="_blank" rel="noreferrer noopener"><img loading="lazy" decoding="async" width="703" height="389" src="https://static-assets.mszpro.com/2024/12/https3A2F2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com2F02F6353302Fd02dcdd1-1dc7-068e-0d90-5b04f9065a60.jpg" alt="tipkit-ng.jpg" class="wp-image-306" srcset="https://static-assets.mszpro.com/2024/12/https3A2F2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com2F02F6353302Fd02dcdd1-1dc7-068e-0d90-5b04f9065a60-300x166.jpg 300w, https://static-assets.mszpro.com/2024/12/https3A2F2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com2F02F6353302Fd02dcdd1-1dc7-068e-0d90-5b04f9065a60.jpg 703w" sizes="auto, (max-width: 703px) 100vw, 703px" /></a></figure>



<p>プロモーションのヒントを表示すべきではありません。TipKitを使用してエラーメッセージを表示しないでください。実行可能なアイテム（例：クリック可能な機能ボタン）に関連したヒントのみを表示し、ヒント内に詳細な手順を表示しないでください（NGの例で示されているように。その場合、ユーザーにオプションを提供するためにカスタムアクションボタンを使用するのが最善）。</p>



<p>(source: public Apple session videos)</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>お読みいただき、ありがとうございました。</p>



<p>ニュースレター:&nbsp;<a href="https://blog.mszpro.com/" rel="noreferrer noopener" target="_blank">https://blog.mszpro.com</a></p>



<p>Mastodon/MissKey:&nbsp;<code>@me@mszpro.com</code>&nbsp;<a href="https://sns.mszpro.com/" rel="noreferrer noopener" target="_blank">https://sns.mszpro.com</a></p>



<p><img loading="lazy" decoding="async" alt=":relaxed:" height="20" src="https://cdn.qiita.com/emoji/twemoji/unicode/263a-fe0f.png" width="20">&nbsp;<a href="https://twitter.com/MszPro" rel="noreferrer noopener" target="_blank">Twitter @MszPro</a></p>



<p><img loading="lazy" decoding="async" alt=":relaxed:" height="20" src="https://cdn.qiita.com/emoji/twemoji/unicode/263a-fe0f.png" width="20">&nbsp;個人ウェブサイト&nbsp;<a href="https://mszpro.com/" rel="noreferrer noopener" target="_blank">https://MszPro.com</a><a href="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F635330%2F33652157-7da9-ee68-3e4d-4b416edfec58.png?ixlib=rb-4.0.0&amp;auto=format&amp;gif-q=60&amp;q=75&amp;s=72b1843d22f83d51fa3fab97a252e91d" target="_blank" rel="noreferrer noopener"></a></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading"><a href="https://qiita.com/mashunzhe/items/016e991fb9020b3eb4c7#%E6%B3%A8"></a>注</h2>



<p>上記内容の一部は、Apple社のサンプルコードから引用しています。ライセンスは下記に添付しています：</p>



<pre class="wp-block-code"><code>Copyright © 2023 Apple Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
</code></pre>



<p><a href="https://b.hatena.ne.jp/entry/s/qiita.com/mashunzhe/items/016e991fb9020b3eb4c7" rel="noreferrer noopener" target="_blank"></a></p><p>The post <a href="https://mszpro.com/tipkit-ios17-ja">SwiftUIでTipKitを使用してユーザーにヒントを表示（iOS 17、WWDC 2023）</a> first appeared on <a href="https://mszpro.com">MszPro・株式会社Smartソフト</a>.</p>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Using TipKit to display a tip to the user in SwiftUI for onboarding</title>
		<link>https://mszpro.com/ios17-tipkit-swiftui</link>
		
		<dc:creator><![CDATA[msz]]></dc:creator>
		<pubDate>Mon, 16 Dec 2024 07:25:23 +0000</pubDate>
				<category><![CDATA[SwiftUI]]></category>
		<category><![CDATA[TipKit]]></category>
		<guid isPermaLink="false">https://mszpro.com/?p=293</guid>

					<description><![CDATA[<p>This article is about using the new TipKit framework for iOS 17 to help the user discover various features within your app. This article will cover: This article is primarily for SwiftUI. This article is written with public resources and may contain screenshots from public Apple documentations and example codes. To see how it works, [&#8230;]</p>
<p>The post <a href="https://mszpro.com/ios17-tipkit-swiftui">Using TipKit to display a tip to the user in SwiftUI for onboarding</a> first appeared on <a href="https://mszpro.com">MszPro・株式会社Smartソフト</a>.</p>]]></description>
										<content:encoded><![CDATA[<p id="9160">This article is about using the new TipKit framework for iOS 17 to help the user discover various features within your app.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1290" height="701" src="https://static-assets.mszpro.com/2024/12/1EPq81uvZWHL5BTDQEzbfcg.jpg" alt="" class="wp-image-298" srcset="https://static-assets.mszpro.com/2024/12/1EPq81uvZWHL5BTDQEzbfcg-300x163.jpg 300w, https://static-assets.mszpro.com/2024/12/1EPq81uvZWHL5BTDQEzbfcg-1024x556.jpg 1024w, https://static-assets.mszpro.com/2024/12/1EPq81uvZWHL5BTDQEzbfcg-768x417.jpg 768w, https://static-assets.mszpro.com/2024/12/1EPq81uvZWHL5BTDQEzbfcg.jpg 1290w" sizes="auto, (max-width: 1290px) 100vw, 1290px" /></figure>



<p id="e1b1">This article will cover:</p>



<ul class="wp-block-list">
<li>displaying an inline tip</li>



<li>displaying floating tip</li>



<li>display tip based on conditions</li>



<li>display tip based on a counter</li>
</ul>



<p id="e167">This article is primarily for SwiftUI.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p id="ccb9">This article is written with public resources and may contain screenshots from public Apple documentations and example codes. To see how it works, please try it yourself with the&nbsp;<strong>Xcode 15</strong></p>
</blockquote>



<figure class="wp-block-video"><video controls src="https://static-assets.mszpro.com/2024/12/TipKit-SwiftUI-explained_-Showing-tips-conditional-swift-macro-rules-new-in-WWDC-2023-iOS-17.mp4" playsinline class="mcloud-attachment-294"></video></figure>



<h1 class="wp-block-heading" id="ea19">Define a&nbsp;<code>Tip</code>&nbsp;object</h1>



<p id="a97a">A&nbsp;<code>Tip</code>&nbsp;object contains the image, title, description, and the actions for a tip. Here is a simple tip:</p>



<pre class="wp-block-preformatted">import TipKit<br><br>struct HashTagPostButtonTip: Tip {<br>    var image: Image? {<br>        Image(systemName: "star.bubble")<br>    }<br>    var title: Text {<br>        Text("Send a Quick Response")<br>    }<br>    var message: Text? {<br>        Text("Double-tap a message, then choose a Tapback, like a ♥︎.")<br>    }<br>}</pre>



<p id="93c4">In the&nbsp;<code>var asset: Image?</code>, you can provide an optional image to be displayed on the left side of the tip.</p>



<p id="fa1c">In the&nbsp;<code>var title: Text</code>, you will provide a SwiftUI Text for the text you want to show as the title of this tip.</p>



<p id="e9fc">In the&nbsp;<code>var message: Text?</code>, you can provide an optional description string that will be displayed at the bottom of the title.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1290" height="790" src="https://static-assets.mszpro.com/2024/12/1nwMwrwk0f9uh9bqIbaKlog.jpg" alt="" class="wp-image-299" srcset="https://static-assets.mszpro.com/2024/12/1nwMwrwk0f9uh9bqIbaKlog-300x184.jpg 300w, https://static-assets.mszpro.com/2024/12/1nwMwrwk0f9uh9bqIbaKlog-1024x627.jpg 1024w, https://static-assets.mszpro.com/2024/12/1nwMwrwk0f9uh9bqIbaKlog-768x470.jpg 768w, https://static-assets.mszpro.com/2024/12/1nwMwrwk0f9uh9bqIbaKlog.jpg 1290w" sizes="auto, (max-width: 1290px) 100vw, 1290px" /></figure>



<p id="5506">There is also a&nbsp;<code>var rules: [Rule]</code>&nbsp;and the&nbsp;<code>var actions: [Action]</code>parameter, which we will talk about in the next section of this article.</p>



<h1 class="wp-block-heading" id="d298">Displaying a tip</h1>



<p id="99ae">There are 2 ways to display a tip.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="720" height="561" src="https://static-assets.mszpro.com/2024/12/11XeeKELynI75QzvldhmYgQ.jpg" alt="" class="wp-image-301" srcset="https://static-assets.mszpro.com/2024/12/11XeeKELynI75QzvldhmYgQ-300x234.jpg 300w, https://static-assets.mszpro.com/2024/12/11XeeKELynI75QzvldhmYgQ.jpg 720w" sizes="auto, (max-width: 720px) 100vw, 720px" /><figcaption class="wp-element-caption">image from public documentation on developer.apple.com</figcaption></figure>



<h1 class="wp-block-heading" id="1bf8">inline tips</h1>



<p id="5ff2">You can display the tip within your view. The tip view will come with an arrow that points to your feature (for example, a button). You can do that by directly including&nbsp;<code>TipView</code>&nbsp;in your view code:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1290" height="682" src="https://static-assets.mszpro.com/2024/12/1zYNiB-TgmkSg_UNqC20OMQ.jpg" alt="" class="wp-image-295" srcset="https://static-assets.mszpro.com/2024/12/1zYNiB-TgmkSg_UNqC20OMQ-300x159.jpg 300w, https://static-assets.mszpro.com/2024/12/1zYNiB-TgmkSg_UNqC20OMQ-1024x541.jpg 1024w, https://static-assets.mszpro.com/2024/12/1zYNiB-TgmkSg_UNqC20OMQ-768x406.jpg 768w, https://static-assets.mszpro.com/2024/12/1zYNiB-TgmkSg_UNqC20OMQ.jpg 1290w" sizes="auto, (max-width: 1290px) 100vw, 1290px" /></figure>



<pre class="wp-block-preformatted">import SwiftUI<br>import TipKit<br><br>struct TipWithArrow: View {<br>    var body: some View {<br>        VStack {<br>            <br>            HStack {<br>                TipView(HashTagPostButtonTip(), arrowEdge: .trailing)<br>                <br>                Image(systemName: "number")<br>                    .font(.system(size: 30))<br>                    .foregroundStyle(.white)<br>                    .padding()<br>                    .background { Circle().foregroundStyle(.blue) }<br>            }<br>            <br>        }<br>        .padding()<br>        .task {<br>            try? Tips.configure([<br>                .displayFrequency(.immediate),<br>                .datastoreLocation(.applicationDefault)<br>            ])<br>        }<br>    }<br>}<br><br>#Preview {<br>    TipWithArrow()<br>}</pre>



<p id="0db0">You can use the&nbsp;<code>arrowEdge</code>&nbsp;parameter to decide which direction the arrow points to. Set to&nbsp;<code>.trailing</code>&nbsp;so that the tip will display an arrow point to the right side (meaning the feature button is on the right); or set it to&nbsp;<code>.leading</code>&nbsp;when the feature button is on the left (and the shown tip is on the right side of the button).</p>



<h1 class="wp-block-heading" id="9492">Floating (popover) tips</h1>



<p id="ef85">You can also use a view modifier to attach a floating tip to a button. This is useful for example when you want to show a tip for a navigation button:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1290" height="740" src="https://static-assets.mszpro.com/2024/12/1OU2pL_DbIDgvWyiq7L7_Cg.jpg" alt="" class="wp-image-300" srcset="https://static-assets.mszpro.com/2024/12/1OU2pL_DbIDgvWyiq7L7_Cg-300x172.jpg 300w, https://static-assets.mszpro.com/2024/12/1OU2pL_DbIDgvWyiq7L7_Cg-1024x587.jpg 1024w, https://static-assets.mszpro.com/2024/12/1OU2pL_DbIDgvWyiq7L7_Cg-768x441.jpg 768w, https://static-assets.mszpro.com/2024/12/1OU2pL_DbIDgvWyiq7L7_Cg.jpg 1290w" sizes="auto, (max-width: 1290px) 100vw, 1290px" /></figure>



<pre class="wp-block-preformatted">struct PopOverTip: View {<br>    <br>    var hashtagButtonTip = HashTagPostButtonTip()<br>    <br>    var body: some View {<br>        VStack {<br>            <br>            Text("Hello world!")<br>            <br>        }<br>        .padding()<br>        .toolbar {<br>            ToolbarItem(placement: .navigationBarTrailing) {<br>                Image(systemName: "number")<br>                    .onTapGesture {<br>                        hashtagButtonTip.invalidate(reason: .actionPerformed)<br>                    }<br>                    .popoverTip(hashtagButtonTip)<br>            }<br>        }<br>        .task {<br>            try? Tips.configure([<br>                .displayFrequency(.immediate),<br>                .datastoreLocation(.applicationDefault)<br>            ])<br>        }<br>    }<br>    <br>}<br><br>#Preview {<br>    PopOverTip()<br>}</pre>



<h1 class="wp-block-heading" id="8212">Tip frequency</h1>



<p id="548d">By default, each tip only shows once.</p>



<p id="8c6c">When you set&nbsp;<code>.displayFrequency(.immediate)</code>, the tip will be immediately shown if the user has not seen the tip before.</p>



<p id="9932">You can also set other display frequencies. For example, if you set it to&nbsp;<code>.hourly</code>, the system makes sure that no more than 1 tip is shown every hour.</p>



<p id="ce2b">You can also customize where the tip data (whether the tips have been shown or not) by using the&nbsp;<code>.datastoreLocation(.applicationDefault)</code>&nbsp;function.</p>



<h1 class="wp-block-heading" id="593e">Show tip when certain condition is met</h1>



<p id="485e">You can only show a tip when certain condition is met. For example, a tip for a premium feature should only be shown if the user has purchased the premium feature.</p>



<p id="45c6">You can define a static variable for the&nbsp;<code>Tip</code>&nbsp;object. Then, you can assign values to that static variable to control whether the tip is shown or not.</p>



<pre class="wp-block-preformatted">import TipKit<br><br>struct PremiumUserOnlyTip: Tip {<br>    <br>    @Parameter<br>    static var isPremiumUser: Bool = false<br>    <br>    var image: Image? {<br>        Image(systemName: "wand.and.rays")<br>    }<br>    var title: Text {<br>        Text("Add an Effect")<br>    }<br>    var message: Text? {<br>        Text("Choose a fun Live Photo effect like Loop or Bounce.")<br>    }<br>    <br>    var rules: [Rule] {<br>        #Rule(Self.$isPremiumUser) {<br>            $0 == true<br>        }<br>    }<br>    <br>}</pre>



<p id="ceb3">On app launch, we can set the static variable&nbsp;<code>isPremiumUser</code>&nbsp;so the tip will only be shown for users who is premium.</p>



<pre class="wp-block-preformatted">PremiumUserOnlyTip.isPremiumUser = isPremiumUser</pre>



<h1 class="wp-block-heading" id="468c">Record user interactions and show tips accordingly</h1>



<p id="c712">You can record user interactions as a counter (like the number of times that the user used your app) and only show tips when the user has met a requirement.</p>



<pre class="wp-block-preformatted">import TipKit<br><br>struct UsageFrequencyBasedTip: Tip {<br>    <br>    static let numerOfTimesOpened: Event = Event(id: "com.example.TipKit.numberOfTimesOpened")<br>    <br>    var image: Image? {<br>        Image(systemName: "star.fill")<br>    }<br>    var title: Text {<br>        Text("Tap to download HD picture")<br>    }<br>    var message: Text? {<br>        Text("Only for premium users")<br>    }<br>    <br>    var rules: [Rule] {<br>        #Rule(Self.numerOfTimesOpened) {<br>            $0.donations.count &gt;= 3<br>        }<br>    }<br>    <br>}</pre>



<p id="bc11">In the above code, we record the number of times user opened the app using an&nbsp;<code>Event</code>&nbsp;object. In the&nbsp;<code>rules</code>&nbsp;parameter, we use a Swift Macro and indicate that the tip will only be shown if the times user opened is larger than or equal to 3.</p>



<p id="b62a">Now, we can increment the counter by using the following code in our app:</p>



<pre class="wp-block-preformatted">Button("tap this button 3 times") {<br>    Task {<br>        await UsageFrequencyBasedTip.numerOfTimesOpened.donate()<br>    }<br>}</pre>



<p id="f6bf">When you call&nbsp;<code>donate()</code>&nbsp;function for 3 times, the tip will be shown.</p>



<h1 class="wp-block-heading" id="aa53">Tip with custom actions</h1>



<p id="8de4">You can also provide your action buttons for a tip:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1290" height="701" src="https://static-assets.mszpro.com/2024/12/1EPq81uvZWHL5BTDQEzbfcg.jpg" alt="" class="wp-image-298" srcset="https://static-assets.mszpro.com/2024/12/1EPq81uvZWHL5BTDQEzbfcg-300x163.jpg 300w, https://static-assets.mszpro.com/2024/12/1EPq81uvZWHL5BTDQEzbfcg-1024x556.jpg 1024w, https://static-assets.mszpro.com/2024/12/1EPq81uvZWHL5BTDQEzbfcg-768x417.jpg 768w, https://static-assets.mszpro.com/2024/12/1EPq81uvZWHL5BTDQEzbfcg.jpg 1290w" sizes="auto, (max-width: 1290px) 100vw, 1290px" /></figure>



<pre class="wp-block-preformatted">import TipKit<br><br>struct TipWithOptions: Tip {<br>    <br>    var image: Image? {<br>        Image(systemName: "star.bubble")<br>    }<br>    <br>    var title: Text {<br>        Text("Send a Quick Response")<br>    }<br>    <br>    var message: Text? {<br>        Text("Double-tap a message, then choose a Tapback, like a ♥︎.")<br>    }<br>    <br>    var actions: [Action] {<br>        return [<br>            .init(id: "learn-more", title: "Learn more", perform: {<br>                print("Learn more tapped")<br>            }),<br>            .init(id: "enable-feature", title: "Enable magic feature", perform: {<br>                print("Enable feature tapped")<br>            })<br>        ]<br>    }<br>    <br>}</pre>



<h1 class="wp-block-heading" id="a60c">Debugging tips</h1>



<p id="8b14">You can debug your tips by using the following function:</p>



<p id="d017">Reset the storage database for whether tips are shown or not:</p>



<pre class="wp-block-preformatted">try? Tips.resetDatastore()</pre>



<p id="9418">The above code must be called before calling&nbsp;<code>Tips/configure(options:)</code></p>



<p id="0357">You can also show all tips regardless of whether a tip has been shown before:</p>



<pre class="wp-block-preformatted">Tips.showAllTipsForTesting()</pre>



<p id="cdb4">You can show a specific tip regardless of whether it has been shown before:</p>



<pre class="wp-block-preformatted">Tips.showTipsForTesting([ExampleTip.self])</pre>



<p id="1ecb">in the parameter, provide an array of the type of the tips.</p>



<p id="02e6">You can also hide all tips, or just hide a specific type of tip:</p>



<pre class="wp-block-preformatted">Tips.hideAllTipsForTesting()<br>Tips.hideTipsForTesting(_ tips: [Tip.Type])</pre>



<h1 class="wp-block-heading" id="e270">Good vs Not Good</h1>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="720" height="402" src="https://static-assets.mszpro.com/2024/12/1Q2ZGzM0zhRh0Dc0k55vlmw.jpg" alt="" class="wp-image-296" srcset="https://static-assets.mszpro.com/2024/12/1Q2ZGzM0zhRh0Dc0k55vlmw-300x168.jpg 300w, https://static-assets.mszpro.com/2024/12/1Q2ZGzM0zhRh0Dc0k55vlmw.jpg 720w" sizes="auto, (max-width: 720px) 100vw, 720px" /><figcaption class="wp-element-caption">Good Examples. image from public documentation on developer.apple.com</figcaption></figure>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="703" height="389" src="https://static-assets.mszpro.com/2024/12/1mu3M2__oczIRp0z7qwUYig.jpg" alt="" class="wp-image-297" srcset="https://static-assets.mszpro.com/2024/12/1mu3M2__oczIRp0z7qwUYig-300x166.jpg 300w, https://static-assets.mszpro.com/2024/12/1mu3M2__oczIRp0z7qwUYig.jpg 703w" sizes="auto, (max-width: 703px) 100vw, 703px" /><figcaption class="wp-element-caption">NG (Not Good). image from public documentation on developer.apple.com</figcaption></figure>



<p id="c038">vYou should not show promotion tips, do not use TipKit to show error messages, only show tip that is associated with an actionable item (for example, a clickable feature button), and do not show detailed steps within the tip (like shown in the example of the NG)</p><p>The post <a href="https://mszpro.com/ios17-tipkit-swiftui">Using TipKit to display a tip to the user in SwiftUI for onboarding</a> first appeared on <a href="https://mszpro.com">MszPro・株式会社Smartソフト</a>.</p>]]></content:encoded>
					
		
		<enclosure url="https://static-assets.mszpro.com/2024/12/TipKit-SwiftUI-explained_-Showing-tips-conditional-swift-macro-rules-new-in-WWDC-2023-iOS-17.mp4" length="53966275" type="video/mp4" />

			</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/

Page Caching using Disk: Enhanced 
Lazy Loading (feed)
Database Caching 5/80 queries in 0.034 seconds using Disk (Request-wide modification query)

Served from: mszpro.com @ 2025-07-06 11:11:07 by W3 Total Cache
-->