Swiftで長押しイベントを10選!実装から応用までの徹底ガイド

Swiftの長押しイベントのサンプルコードイメージSwift
この記事は約27分で読めます。

 

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

基本的な知識があればカスタムコードを使って機能追加、目的を達成できるように作ってあります。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を凌駕する現役のプログラマチームによって監修されています。

サイト内のコードを共有する場合は、参照元として引用して下さいますと幸いです

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

皆さん、Swiftを使用してアプリ開発を行っている際に、ユーザーが画面上の特定のオブジェクトを長押しすることで何らかのアクションをトリガーしたいと考えたことはありませんか?

長押しイベントは、アプリのUXを向上させるための素晴らしいツールとして使用されることが多いです。

この記事を読めば、Swiftで長押しイベントをどのように実装するか、またそれをカスタマイズや応用する方法について詳しく学べるようになります。

●Swiftでの長押しイベントの基本

○長押しイベントとは

長押しイベントとは、ユーザーが画面の特定のエリアやオブジェクトを一定時間以上タッチし続けることで発生するイベントのことを指します。

iOSの場合、UIGestureRecognizerクラスのサブクラスであるUILongPressGestureRecognizerを使用することで、このイベントを検知することができます。

長押しイベントは、例えば、特定のアイテムを長押ししてそのアイテムの詳細を表示したり、編集モードに入ったりする場面でよく使用されます。

この機能を活用することで、アプリの操作性を大きく向上させることができます。

●Swiftでの長押しイベントの実装方法

Swiftで長押しイベントを実装する際の基本的な手順を紹介します。

具体的には、UILongPressGestureRecognizerを使用して、オブジェクトに対する長押しイベントを検知する方法について解説します。

○サンプルコード1:基本的な長押しイベントの検知

このコードではUILabelを使って長押しイベントを検知する方法を紹介します。

下記のサンプルコードは、UILabelを長押しすると「ラベルが長押しされました」というメッセージが表示されるものです。

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let label = UILabel(frame: CGRect(x: 50, y: 50, width: 200, height: 50))
        label.text = "長押ししてください"
        view.addSubview(label)

        let longPress = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress))
        label.addGestureRecognizer(longPress)
        label.isUserInteractionEnabled = true
    }

    @objc func handleLongPress(sender: UILongPressGestureRecognizer) {
        if sender.state == .began {
            print("ラベルが長押しされました")
        }
    }
}

このコードを実行すると、ラベルが表示され、そのラベルを長押しするとコンソールに「ラベルが長押しされました」というメッセージが出力されます。

○サンプルコード2:長押し時間による処理の変更

長押しの時間に応じて異なるアクションをトリガーしたい場合は、UILongPressGestureRecognizerのminimumPressDurationプロパティを利用します。

このコードでは、3秒以上長押しするとメッセージが表示される例を紹介します。

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let label = UILabel(frame: CGRect(x: 50, y: 100, width: 200, height: 50))
        label.text = "3秒以上長押ししてください"
        view.addSubview(label)

        let longPress = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress))
        longPress.minimumPressDuration = 3.0  // 3秒以上の長押しを検知
        label.addGestureRecognizer(longPress)
        label.isUserInteractionEnabled = true
    }

    @objc func handleLongPress(sender: UILongPressGestureRecognizer) {
        if sender.state == .began {
            print("3秒以上ラベルが長押しされました")
        }
    }
}

このコードを実行すると、ラベルが表示されます。

そして、ラベルを3秒以上長押しするとコンソールに「3秒以上ラベルが長押しされました」というメッセージが出力されます。

○サンプルコード3:長押し時のビジュアルフィードバックの追加

ユーザーに長押しイベントが発生していることをビジュアルで伝えるフィードバックは、UX向上のために重要です。

このコードでは、長押し時にラベルの背景色が変わる例を紹介します。

import UIKit

class ViewController: UIViewController {

    let label = UILabel(frame: CGRect(x: 50, y: 150, width: 200, height: 50))

    override func viewDidLoad() {
        super.viewDidLoad()

        label.text = "長押しで色が変わります"
        view.addSubview(label)

        let longPress = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress))
        label.addGestureRecognizer(longPress)
        label.isUserInteractionEnabled = true
    }

    @objc func handleLongPress(sender: UILongPressGestureRecognizer) {
        if sender.state == .began {
            label.backgroundColor = .yellow
        } else if sender.state == .ended || sender.state == .cancelled {
            label.backgroundColor = .clear
        }
    }
}

このコードを実行すると、ラベルが表示されます。ラベルを長押しすると背景色が黄色になり、手を離すと元に戻ります。

●Swiftでの長押しイベントの応用例

Swiftにおける長押しイベントは基本的な実装だけでなく、さまざまな応用例が考えられます。

ここでは、長押しイベントを利用した具体的なアプリケーションの実例をいくつか紹介し、サンプルコードを交えて詳しく解説します。

○サンプルコード4:長押しでメニューを表示

このコードでは、UILabelを長押しするとポップアップメニューが表示されます。

UIMenuControllerを利用して、独自のメニューアイテムを設定します。

import UIKit

class ViewController: UIViewController {

    let label = UILabel(frame: CGRect(x: 50, y: 50, width: 200, height: 50))

    override func viewDidLoad() {
        super.viewDidLoad()

        label.text = "長押しでメニュー表示"
        view.addSubview(label)

        let longPress = UILongPressGestureRecognizer(target: self, action: #selector(showMenu))
        label.addGestureRecognizer(longPress)
        label.isUserInteractionEnabled = true
    }

    @objc func showMenu(sender: UILongPressGestureRecognizer) {
        if sender.state == .began {
            let menu = UIMenuController.shared
            menu.menuItems = [UIMenuItem(title: "コピー", action: #selector(copyText)), UIMenuItem(title: "共有", action: #selector(shareText))]
            menu.setTargetRect(label.frame, in: view)
            menu.setMenuVisible(true, animated: true)
        }
    }

    @objc func copyText() {
        UIPasteboard.general.string = label.text
        print("テキストをコピーしました")
    }

    @objc func shareText() {
        let activityVC = UIActivityViewController(activityItems: [label.text ?? ""], applicationActivities: nil)
        present(activityVC, animated: true, completion: nil)
    }
}

このコードを実行すると、UILabelが画面上に表示されます。

このラベルを長押しすると「コピー」と「共有」という二つのメニュー項目が表示され、それぞれのアクションが起動します。

○サンプルコード5:長押しでアイコンの拡大・縮小

ユーザーがアイコンや画像を長押しすることで、詳細な情報を表示する際に拡大・縮小のアニメーションを追加すると、視覚的なフィードバックを提供できます。

下記のコードでは、UIImageViewを長押しすると拡大し、手を離すと元のサイズに戻る例を表します。

import UIKit

class ViewController: UIViewController {

    let imageView = UIImageView(frame: CGRect(x: 50, y: 150, width: 100, height: 100))

    override func viewDidLoad() {
        super.viewDidLoad()

        imageView.image = UIImage(named: "sampleIcon")
        view.addSubview(imageView)

        let longPress = UILongPressGestureRecognizer(target: self, action: #selector(handleZoom))
        imageView.addGestureRecognizer(longPress)
        imageView.isUserInteractionEnabled = true
    }

    @objc func handleZoom(sender: UILongPressGestureRecognizer) {
        if sender.state == .began {
            UIView.animate(withDuration: 0.3) {
                self.imageView.transform = CGAffineTransform(scaleX: 1.5, y: 1.5)
            }
        } else if sender.state == .ended || sender.state == .cancelled {
            UIView.animate(withDuration: 0.3) {
                self.imageView.transform = CGAffineTransform.identity
            }
        }
    }
}

このコードを実行すると、アイコンが中央に表示されます。

アイコンを長押しすると1.5倍のサイズに拡大し、手を離すと元のサイズに戻ります。

○サンプルコード6:長押しで画像の詳細表示

ユーザーが画像を長押しすることで、詳細情報や拡大画像を表示する機能は、多くのアプリケーションで求められます。

こちらのサンプルコードでは、UIImageView上での長押し操作を検出して、詳細画像をモーダルビューとして表示する方法を紹介します。

import UIKit

class ViewController: UIViewController {

    let imageView = UIImageView(frame: CGRect(x: 30, y: 80, width: 150, height: 150))

    override func viewDidLoad() {
        super.viewDidLoad()

        imageView.image = UIImage(named: "sampleImage")
        view.addSubview(imageView)

        let longPress = UILongPressGestureRecognizer(target: self, action: #selector(displayDetails))
        imageView.addGestureRecognizer(longPress)
        imageView.isUserInteractionEnabled = true
    }

    @objc func displayDetails() {
        let detailVC = UIViewController()
        detailVC.view.backgroundColor = .white
        let detailImageView = UIImageView(frame: detailVC.view.bounds)
        detailImageView.image = UIImage(named: "sampleImage_detail")
        detailImageView.contentMode = .scaleAspectFit
        detailVC.view.addSubview(detailImageView)
        self.present(detailVC, animated: true, completion: nil)
    }
}

このコードではUIImageViewを配置し、その上での長押しイベントを検知します。

長押しを検出すると、新たにUIViewControllerをモーダル表示し、その中に詳細な画像(sampleImage_detail)を表示します。

この方法を使用すると、ユーザーは元の画像を長押しするだけで、詳細な画像や情報を迅速に確認することができます。

○サンプルコード7:長押しでアイテムの移動

アイテムのドラッグ&ドロップは、ユーザーの操作感を向上させる要素としてアプリ内でよく見られます。

下記のコードでは、UIViewを長押しして移動する例を表します。

import UIKit

class ViewController: UIViewController {

    let movableItem = UIView(frame: CGRect(x: 50, y: 150, width: 70, height: 70))

    override func viewDidLoad() {
        super.viewDidLoad()

        movableItem.backgroundColor = .blue
        view.addSubview(movableItem)

        let longPress = UILongPressGestureRecognizer(target: self, action: #selector(handleDrag))
        movableItem.addGestureRecognizer(longPress)
    }

    @objc func handleDrag(sender: UILongPressGestureRecognizer) {
        let location = sender.location(in: view)
        if sender.state == .began || sender.state == .changed {
            movableItem.center = location
        }
    }
}

ユーザーが青い四角形のUIViewを長押しすると、その位置に合わせて動かすことができます。

この機能は、ユーザーの直感的な操作を可能にし、使いやすさを追求する際に有効です。

○サンプルコード8:長押しでアイテムの削除

ユーザーインターフェースの中で、アイテムやコンテンツを長押しすることで削除する機能は非常に直感的です。

ここでは、Swiftを使用して、長押しでアイテムを削除する方法を解説します。

import UIKit

class ViewController: UIViewController {

    let itemToDelete = UIView(frame: CGRect(x: 100, y: 200, width: 100, height: 100))

    override func viewDidLoad() {
        super.viewDidLoad()

        itemToDelete.backgroundColor = .red
        view.addSubview(itemToDelete)

        let longPress = UILongPressGestureRecognizer(target: self, action: #selector(handleDelete))
        itemToDelete.addGestureRecognizer(longPress)
    }

    @objc func handleDelete(sender: UILongPressGestureRecognizer) {
        if sender.state == .began {
            let alert = UIAlertController(title: "削除確認", message: "このアイテムを削除しますか?", preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "はい", style: .destructive, handler: { _ in
                self.itemToDelete.removeFromSuperview()
            }))
            alert.addAction(UIAlertAction(title: "いいえ", style: .cancel, handler: nil))
            self.present(alert, animated: true)
        }
    }
}

このコードでは、画面上に赤い四角形のアイテムを表示しています。

このアイテムを長押しすると、アラートダイアログが表示され、ユーザーにアイテムの削除を確認します。

はいを選択すると、赤い四角形のアイテムが画面から削除されます。

このようにして、ユーザーの操作感を向上させながら、間違ってアイテムを削除するリスクを低減することができます。

○サンプルコード9:長押しで色の変更

色を変更するというシンプルなアクションも、長押しイベントを利用して実装することができます。

次に、UIViewの色を長押しで変更するサンプルを紹介します。

import UIKit

class ViewController: UIViewController {

    let colorChangingView = UIView(frame: CGRect(x: 80, y: 150, width: 150, height: 150))

    override func viewDidLoad() {
        super.viewDidLoad()

        colorChangingView.backgroundColor = .green
        view.addSubview(colorChangingView)

        let longPress = UILongPressGestureRecognizer(target: self, action: #selector(changeColor))
        colorChangingView.addGestureRecognizer(longPress)
    }

    @objc func changeColor() {
        let colors: [UIColor] = [.green, .blue, .yellow, .orange, .purple]
        let randomColor = colors[Int(arc4random_uniform(UInt32(colors.count)))]
        colorChangingView.backgroundColor = randomColor
    }
}

上記のコードでは、初めに緑色の四角形が表示されます。

この四角形を長押しすると、ランダムな色に変わります。

この機能は、ユーザーに対して直感的なフィードバックを提供することができ、アプリの操作体験を向上させます。

○サンプルコード10:長押しで音声再生

Swiftで音声再生を実装する際の一例として、長押しで特定の音声ファイルを再生する方法を解説します。

import UIKit
import AVFoundation

class ViewController: UIViewController {

    var audioPlayer: AVAudioPlayer?

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let playButton = UIButton(frame: CGRect(x: 100, y: 250, width: 100, height: 50))
        playButton.setTitle("音声再生", for: .normal)
        playButton.backgroundColor = .black
        view.addSubview(playButton)

        let longPress = UILongPressGestureRecognizer(target: self, action: #selector(playSound))
        playButton.addGestureRecognizer(longPress)

        guard let soundURL = Bundle.main.url(forResource: "sampleSound", withExtension: "mp3") else { return }
        do {
            audioPlayer = try AVAudioPlayer(contentsOf: soundURL)
        } catch {
            print("音声ファイルの読み込みに失敗しました。")
        }
    }

    @objc func playSound() {
        audioPlayer?.play()
    }
}

このコードでは、長押し操作を検知するボタンを配置しています。

ボタンを長押しすると、sampleSound.mp3という名前の音声ファイルが再生されます。

音声の再生には、AVFoundationフレームワークのAVAudioPlayerクラスを利用しています。

この方法を使用すると、ユーザーはボタンを長押しすることで、関連する音声や効果音を瞬時に再生することができます。

●長押しイベントの注意点と対処法

長押しイベントはユーザーエクスペリエンスを高めるための素晴らしいツールですが、その実装にはいくつかの注意点があります。

特に、デバイスやOSの違い、そして処理が重い場合の対応が必要です。

○デバイスやOSの違いによる注意点

iOSデバイスは多岐にわたり、それぞれのデバイスやOSバージョンによって長押しの感度や動作が異なることがあります。

例えば、古いiOSバージョンでは、新しいバージョンとは異なる長押しの動作をすることが考えられます。

また、特定のデバイスやOSバージョンでのみ発生する問題に対処するためのサンプルコードを紹介します。

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var longPressButton: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()

        let longPress = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress))
        longPress.minimumPressDuration = determinePressDuration()
        longPressButton.addGestureRecognizer(longPress)
    }

    @objc func handleLongPress() {
        // 長押し時の処理を実装
    }

    func determinePressDuration() -> TimeInterval {
        if #available(iOS 14.0, *) {
            return 0.5
        } else {
            return 1.0
        }
    }
}

このコードを実行すると、iOS 14.0以降では長押しの感度が0.5秒、それよりも前のバージョンでは1.0秒となるように調整されます。

これにより、OSバージョンによる違いを最小限に抑えることができます。

○処理が重いときの対応策

長押しイベント中に重い処理を行うと、アプリのレスポンスが遅れる可能性があります。

このような場合、非同期処理を使用してユーザー体験を損なわないようにする必要があります。

下記のサンプルコードでは、長押しイベントで重い処理を非同期で実行する方法を表しています。

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var longPressButton: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let longPress = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress))
        longPressButton.addGestureRecognizer(longPress)
    }

    @objc func handleLongPress() {
        DispatchQueue.global(qos: .userInitiated).async {
            // 重い処理を実行
            self.performHeavyTask()
            
            DispatchQueue.main.async {
                // 重い処理の後にUIの更新などの処理を行う
            }
        }
    }
    
    func performHeavyTask() {
        // 何かの重い処理
        Thread.sleep(forTimeInterval: 2.0)
    }
}

このコードを実行すると、長押しイベントが検知された際にperformHeavyTask関数が非同期で実行されます。

その後、必要に応じてメインスレッドでUIの更新などの処理を行うことができます。

このように、非同期処理を利用することで、ユーザーがアプリをスムーズに操作できるようにすることが重要です。

●カスタマイズ方法

Swiftでの長押しイベントは非常に柔軟で、多くのカスタマイズが可能です。

ここでは、長押しの感度や時間を調整する方法や、外部ライブラリを利用してのカスタマイズ例を解説します。

○長押しの感度や時間を変更する方法

長押しイベントの感知にかかる時間は、UILongPressGestureRecognizerminimumPressDurationプロパティで調整できます。

この値を小さくすると、より短い時間での長押しを検知できるようになります。

逆に、この値を大きくすると、より長い時間の長押しを要求するようになります。

ここでは、長押しの感知時間を0.3秒に設定したサンプルコードを紹介します。

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var longPressButton: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()

        let longPress = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress))
        longPress.minimumPressDuration = 0.3
        longPressButton.addGestureRecognizer(longPress)
    }

    @objc func handleLongPress() {
        print("長押しを検知しました")
    }
}

このコードでは、longPress.minimumPressDuration = 0.3という部分で、長押しの感知時間を0.3秒に設定しています。

このコードを実行すると、ボタンを0.3秒間長押しすると、「長押しを検知しました」というメッセージがコンソールに表示されます。

○外部ライブラリを使用したカスタマイズ例

Swiftのコミュニティは活発で、多くの外部ライブラリが提供されています。

これらのライブラリを利用することで、長押しイベントのカスタマイズや拡張がさらに容易になります。

例として、「LongPressPopUp」ライブラリを使用したカスタマイズ例を紹介します。

このライブラリは、長押し時にポップアップメニューを簡単に表示することができます。

まず、CocoaPodsやSwift Package Managerを使用して「LongPressPopUp」をプロジェクトに追加します。

次に、ライブラリを利用してポップアップメニューを表示するサンプルコードを紹介します。

import UIKit
import LongPressPopUp

class ViewController: UIViewController {

    @IBOutlet weak var longPressButton: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let longPress = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress))
        longPressButton.addGestureRecognizer(longPress)
    }

    @objc func handleLongPress() {
        let popUpMenu = LongPressPopUp(items: ["選択1", "選択2", "選択3"])
        popUpMenu.show(from: longPressButton)
    }
}

このコードを実行すると、ボタンを長押しすると、「選択1」「選択2」「選択3」の3つの選択肢が含まれるポップアップメニューが表示されます。

このように、外部ライブラリを利用することで、標準の長押しイベントの機能を拡張し、多彩なカスタマイズを実現することができます。

まとめ

Swiftでの長押しイベントは、UIの中で非常に役立つ機能の一つです。

この記事を通じて、その基本的な実装方法から応用例、さらにはカスタマイズ方法まで、幅広く学ぶことができました。

長押しイベントをうまく利用することで、ユーザーにとってより直感的で使いやすいアプリケーションを作成することが可能になります。

また、Swiftのコミュニティの力を借りることで、さらに高度なカスタマイズや拡張も手軽に行うことができるので、是非とも外部ライブラリの活用も検討してみてください。

最後に、長押しイベントを使用する際は、ユーザビリティを最優先に考え、必要な機能やカスタマイズを適切に取り入れることで、ユーザーの期待を超えるようなアプリケーションを目指しましょう。