【SwiftUI】クリップボードにコピーする方法!自作ボタンでバルーン表示

この記事からわかること
- SwiftUIでテキストをクリップボードにコピーする方法
- 「コピーしました」のバルーン表示の実装方法
- UIPasteboard.generalの使い方
index
[open]
\ アプリをリリースしました /
アプリ開発でなにかと必要になる小技「クリップボードにコピー」。実際の実装方法と使い方、「コピーしました」のバルーン表示の自作方法をまとめていきます。
テキストをクリップボードにコピーさせる方法
SwiftでユーザーのクリップボードへテキストなどをコピーさせるにはUIPasteboard
クラスを使用します。
class UIPasteboard : NSObject
UIPasteboard
クラスのgeneral
プロパティの中に文字列やURL、画像などの様々な種類のデータを保持することができるので、ここにそれぞれ値を入れ込めばクリップボードにコピーされた状態になります。
// 文字列
UIPasteboard.general.string = "コピーさせたい文字列"
// 画像
UIPasteboard.general.image = UIImage(named: "画像名")
// URL
UIPasteboard.general.url = URL(string: "https://www.amefure.com")
// 色
UIPasteboard.general.color = UIColor.white
あとはこの処理をボタンのアクションの中などで実行すれば押しただけで任意の値をコピーさせることができるようになります。
アプリ内の文字列はコピーできない?
そもそもアプリ内でText表示させている文字列などは触ろうとしても選択/コピーすることができない仕様になっています。
なのでユーザーがコピーできるようにするには今回のようにクリップボードにコードからコピーさせるか下記記事のように選択/コピーが可能になるようにモディファイアを追加しなければいけません。
おすすめ記事:【Swift UI】Textを選択/コピー可能にする方法
「コピーしました」バルーン表示の自作
今回はユーザビリティを高めるためにコピーボタンの作成と押されたら「コピーしました」とメッセージ(バルーン表示)が出るようにしていきたいと思います。

フレームワークはSwift UIを使用して作成していきます。
ポイント
- バルーン表示用のクラスを作成
- プロパティopacity:バルーンの透明感を制御
- プロパティisPreview:バルーンの表示/非表示を制御
- ボタンクリックでバルーン表示後徐々に消えていく
- timerを使ってopacityを操作してアニメーションを実装
バルーン表示用のクラスを作成
ますばクラスを作成します。作成するMessageBalloon
クラスはプロパティの変化を観測できるようにObservableObject
プロトコルに準拠させておき、プロパティには@Published
を付与しておきます。
// コピーしました用のメッセージバルーン
class MessageBalloon:ObservableObject{
// opacityモディファイアの引数に使用
@Published var opacity:Double = 10.0
// 表示/非表示を切り替える用
@Published var isPreview:Bool = false
private var timer = Timer()
// Double型にキャスト&opacityモディファイア用の数値に割り算
func castOpacity() -> Double{
Double(self.opacity / 10)
}
// opacityを徐々に減らすことでアニメーションを実装
func vanishMessage(){
timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true){ _ in
self.opacity = self.opacity - 1.0 // デクリメント
if(self.opacity == 0.0){
self.isPreview = false // 非表示
self.opacity = 10.0 // 初期値リセット
self.timer.invalidate() // タイマーストップ
}
}
}
}
opacity
モディファイアでの指定はDouble型で「0〜1」ですが、vanishMessage
メソッドで「-0.1」ずつに減らしていくと正確な引き算ができない(Swiftの仕様上)ので「0〜10」の間で「-1」ずつ変化させるようにします。
vanishMessage
メソッドではTimer
を使用して0.1秒ごとに処理をリピートさせ、opacity
の値が0になったタイミングで非表示にしつつ、opacity
を初期値に戻しておきます。
ちなみにvanishMessage
メソッドのようなクロージャの中で自身のプロパティの値を変更するのは構造体ではできずに以下のようなエラーになるので注意してください。
Escaping closure captures mutating 'self' parameter
コピーボタンの実装
続いてコピーボタンを作っていきます。まずはクラスの変更を観測したいので@ObservedObject
をつけてmessageBalloon
のインスタンスを作成します。Button構造体のアクションの中でクリップボードへのコピー処理とバルーン表示を表示させる(isPreviewにtrue)処理を実装します。ボタンが押され表示されている間に再度押されないようにdisabled(messageAlert.isPreview)
を渡して無効にしておきます。
Button(action: {
UIPasteboard.general.string = "コピーしたい文字列"
messageAlert.isPreview = true
messageAlert.vanishMessage()
}, label: {
Image(systemName: "doc.on.doc")
.foregroundColor(.gray)
.frame(width: 65)
}).disabled(messageAlert.isPreview)
「コピーしました」バルーンの実装
「コピーしました」部分はTextで実装します。あとはデザインと表示位置を調整してopacity
モディファイアにcastOpacity
メソッドを渡せばOKです。
クラスのインスタンスを作成する際は変更を検知できるように@ObservedObject
を付与しておくのを忘れないようにしてください。
@ObservedObject var messageAlert = MessageBalloon()
ZStack {
if (messageAlert.isPreview){
Text("コピーしました")
.font(.system(size: 8))
.padding(3)
.background(Color(red: 0.3, green: 0.3 ,blue: 0.3))
.foregroundColor(.white)
.opacity(messageAlert.castOpacity())
.cornerRadius(5)
.offset(x: -5, y: -20)
}
// さっきのボタン
} // ZStack
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。