[Tips]UIAlertControllerでアラートやアクションシートを表示するには?

はじめに

iOSではUIActionControllerを使用して、ポップアップでアラートを表示したり、選択肢(アクションシート)を表示したりして、ユーザーに項目を選択させることができます。

iPhoneにおいては、アラートの表示も選択肢の表示も問題なく動作します。しかし、iPadにおいてはiPhoneと同様の実装を行うと、アラートは動作しますが、選択肢(アクションシート)の表示は落ちてしまいます。

本TipsではiPhoneとiPadでアラートとアクションシートを表示する方法について説明します。

今回作成するサンプルは以下のようなものです。

環境

Xcode:9.4.1
Swift:4.1.2

AlertControllerの使用方法

はじめに、AlertControllerの使用してアラートを表示する方法について説明します。これが基本となります。

Xcodeを起動してSingle View Appプロジェクトを作成します。

次にMain.storyboardを開いてUIButtonを1つ貼り付けます。

続いて、貼り付けたButtonのアクション接続を作成します。

名称は、buttonAlertとしました。

コードはiPhoneもiPadも同一のもので動作します。コード例を以下に示します。

①の部分でUIAlertControllerのインスタンスを作成し、②と③でOKボタンとキャンセルボタンを作成しています。

④で、①で作成したインスタンスにOKボタンとキャンセルボタンを追加し、⑤でアラートの表示をしています。詳細はコード中のコメントを参照してください。

@IBAction func buttonAlert(_ sender: Any) {
    // ①UIAlertControllerクラスのインスタンスを生成する
    // titleにタイトル, messegeにメッセージ, prefereedStyleにスタイルを指定する
    // preferredStyleにUIAlertControllerStyle.alertを指定してアラート表示にする
    let alert: UIAlertController = UIAlertController(
        title: "アラート表示",
        message: "メールを送信します。よろしいですか?",
        preferredStyle: UIAlertControllerStyle.alert)
    
    // ②OKボタンの作成
    // titleにボタンのテキストを、styleにUIAlertActionStyle.defaultを
    // handlerにボタンが押された時の処理をクロージャで実装する
    let okAction: UIAlertAction =
        UIAlertAction(
            title: "OK",
            style: UIAlertActionStyle.default,
            handler:{
                (action: UIAlertAction!) -> Void in
                print("OK")
    })
    
    // ③キャンセルボタンの作成
    // OKボタンと同様に作成
    let cancelAction: UIAlertAction =
        UIAlertAction(
            title: "キャンセル",
            style: UIAlertActionStyle.cancel,
            handler:{
                (action: UIAlertAction!) -> Void in
                print("Cancel")
    })
    
    // ④UIAlertControllerのインスタンスに作成したボタンを追加
    alert.addAction(cancelAction)
    alert.addAction(okAction)
    
    // ⑤アラートを表示
    present(alert, animated: true, completion: nil)
}

上記の実行例を以下に示します。

iPhoneでのActionSheet表示

UIAlertControllerでのアラート表示方法を理解したら、iPhoneにおける選択肢(ActionSheet)の表示方法を理解しましょう。

コード例を以下に示します。この例ではユーザーに「バスケットボール」「野球」「テニス」の選択肢を示し、選択してもらうためのアクションシートを表示します。

はじめに①の部分でUIAlertControllerのインスタンスを生成します。アラートの時との違いは preferredStyle に UIAlertControllerStyle.actionSheet を指定するという部分です。

②では選択肢を作成し、①で作成したインスタンスに追加をしています。アラートのOKボタン作成時のコードとほぼ同様です。

最後に③でアクションシートを表示します。

@IBAction func buttonAlert(_ sender: Any) {
    // ①UIAlertControllerクラスのインスタンスを生成する
    // titleにタイトル, messegeにメッセージ, prefereedStyleにスタイルを指定する
    // preferredStyleにUIAlertControllerStyle.actionSheetを指定してアクションシートを表示する
    let actionSheet: UIAlertController = UIAlertController(
        title: "選択肢を表示",
        message: "好きなスポーツを選択してください",
        preferredStyle: UIAlertControllerStyle.actionSheet)

    // ②選択肢の作成と追加
    // titleに選択肢のテキストを、styleに.defaultを
    // handlerにボタンが押された時の処理をクロージャで実装する
    actionSheet.addAction(
        UIAlertAction(title: "バスケットボール",
                      style: .default,
                      handler: {
                        (action: UIAlertAction!) -> Void in
                            print("バスケットボール")
        })
    )

    // ②選択肢の作成と追加
    actionSheet.addAction(
        UIAlertAction(title: "野球",
                      style: .default,
                      handler: {
                        (action: UIAlertAction!) -> Void in
                        print("野球")
        })
    )
    
    // ②選択肢の作成と追加
    actionSheet.addAction(
        UIAlertAction(title: "テニス",
                      style: .default,
                      handler: {
                        (action: UIAlertAction!) -> Void in
                        print("テニス")
        })
    )

    // ③アクションシートを表示
    present(actionSheet, animated: true, completion: nil)
}

上記の実行例を以下に示します。

iPadでのActionSheet表示

iPadではiPhoneと同様に実装すると落ちてしまいます。

そこで、コードを以下のように実装します。

違いは以下コードの③の部分のみです。

iPadでアクションシートを表示するには、アクションシートを表示するViewと表示位置を指定する必要があります。

Viewは popoverPresentationController?.sourceView に、表示位置は popoverPresentationController?.sourceRect に指定します。このとき表示位置をsender(つまりはアクションシートを表示するために押されたボタン)を指定することで、そのボタンから吹き出しのようにアクションシートが表示されるようになります。

@IBAction func buttonAlert(_ sender: Any) {
    // ①UIAlertControllerクラスのインスタンスを生成する
    // titleにタイトル, messegeにメッセージ, prefereedStyleにスタイルを指定する
    // preferredStyleにUIAlertControllerStyle.actionSheetを指定してアクションシートを表示する
    let actionSheet: UIAlertController = UIAlertController(
        title: "選択肢を表示",
        message: "好きなスポーツを選択してください",
        preferredStyle: UIAlertControllerStyle.actionSheet)

    // ②選択肢の作成と追加
    // titleに選択肢のテキストを、styleに.defaultを
    // handlerにボタンが押された時の処理をクロージャで実装する
    actionSheet.addAction(
        UIAlertAction(title: "バスケットボール",
                      style: .default,
                      handler: {
                        (action: UIAlertAction!) -> Void in
                            print("バスケットボール")
        })
    )

    // ②選択肢の作成と追加
    actionSheet.addAction(
        UIAlertAction(title: "野球",
                      style: .default,
                      handler: {
                        (action: UIAlertAction!) -> Void in
                        print("野球")
        })
    )
    
    // ②選択肢の作成と追加
    actionSheet.addAction(
        UIAlertAction(title: "テニス",
                      style: .default,
                      handler: {
                        (action: UIAlertAction!) -> Void in
                        print("テニス")
        })
    )

    // ③表示するViewと表示位置を指定する
    actionSheet.popoverPresentationController?.sourceView = view
    actionSheet.popoverPresentationController?.sourceRect = (sender as AnyObject).frame
    
    // ④アクションシートを表示
    present(actionSheet, animated: true, completion: nil)
}

③の部分を以下のように変更することで、デバイスを自動的に判断して実行できるようになります。このように記述すればiPhoneでもiPadでも動作させることが可能になります。

デバイスの判定については「[Tips] 使用中のデバイスを判定する」の記事を参考にしてください。

// ③表示するViewと表示位置を指定する(デバイス自動判定版)
if UIDevice.current.userInterfaceIdiom  == .pad {
    actionSheet.popoverPresentationController?.sourceView = view
    actionSheet.popoverPresentationController?.sourceRect = (sender as AnyObject).frame
}

上記の実行例を以下に示します。

ボタンのスタイルについて

最後にボタンのスタイルについて説明します。

ボタンのスタイルは以下に示す3種類を指定することができます。

スタイル 説明
default 標準ボタン用
cancel キャンセルボタン用
destructive 赤文字

必要に応じて選択するようにしましょう。

[Tips]コードスニペットを作成するには?

はじめに

よく使用するコードをなんども入力するのは面倒ですね。

そこで、よく使用するコードはライブラリとして登録して使い回せるようにします。これをコードスニペットと呼びます。

今回は、コードスニペットを作成する方法を説明します。

環境

Xcode:9.4.1
Swift:4.1.2

コードスニペットの登録方法

以下のようなコメントがあるとします。これを毎回入力するのもコピペして使いまわすのも大変です。

///==================================================
/// 機能:
/// 引数:
///     引数1:
///     引数2:
/// 戻り値:
///
/// Create Date:
/// Update Date:
///==================================================

そこで、コードスニペットとして登録します。

はじめにXcode上でコードスニペットにしたいコードを入力します。

次に、入力したコードを選択して、コードスニペットライブラリにドラッグ&ドロップします。

以下のように詳細情報を入力する画面が表示されるので必要に応じて編集します。

  • Title:登録するコードスニペットのタイトルを入力
  • Summary:コードスニペットの説明を入力
  • Platform:iOSやmacOSなど、コードスニペットを使用するターゲットを選択します。
  • Language:対象の言語を選択します。Swiftが対象の場合は「Swift」を選択。
  • Completion Shortcut:コードスニペットを入力するときのショートカット文字列を入力します。Xcode上でこの文字を入力すると、ここで登録したコードスニペットが入力されます。
  • Completion Scopes:ここで設定したスコープ内で入力補完されます。+を押すことで、複数指定が可能です。

プレースホルダも作成することができます。プレースホルダは、登録したコードスニペット内でTabキーを押して移動できる文字列です。コードスニペットのコードを入力したあとに、変更したい場所がある場合はプレースホルダにしておきます。

プレースホルダを作成するにはコードスニペット内で <# 文字列 #> と入力します。

Completion Scopes

Completion Scopesについて、もう少し詳しく説明します。

Completion Scopesは実際には以下の種類があります。

Completion Scopes 説明
ALL 全てのスコープで使用可能
String or Comment 文字列リテラルとコメント内で使用可能
Top Level importよりも下のレベルで@interface, @implementationより外のスコープ

[Tips]ハンバーガーメニューを作成するには?

はじめに

ハンバーガーメニューは、様々な作成方法があります。

ここでは、メインのViewControllerにハンバーガーボタンを設置して、タップされた時に別のViewControllerをオーバーレイ表示させてメニューを表示させる方法を紹介します。

環境

Xcode:9.4.1
Swift:4.1.2

1.Navigation Controllerの配置

Single View Appのプロジェクトを作成したら、Storyboardを開いてメインのViewControllerを選択します。

次に、メニューの[Editor]-[Embed in]-[Navigation Controller]を選択します。

すると、以下のようにNavigation Controllerが追加されて、メインのViewControllerにはNavigation Barが表示されます。

2.ハンバーガーアイコンの設置

次にハンバーガーアイコンを設置します。

はじめに、以下のような画像を準備して、Assetsフォルダに入れます。Assetsフォルダ場では、追加したハンバーガーアイコンの名前を「menu」にしておきます。

続いてメインのViewControllerにあるNabigation Barの左側に、Bar Button Itemを追加します。

続いて、配置したBar Button Itemに先ほど追加したハンバーガーアイコンを設定します。System Itemを「Custom」に、Imageを「menu」にします。これでハンバーガーアイコンが表示されます。

3.ハンバーガーメニュー用のビューを作成する

ハンバーガーボタンをタップした時に表示されるメニューを作成します。メニューは、ViewControllerで作成します。

新しくViewControllerを追加してください。

次にハンバーガーボタンを[control]キーを押しながら、追加したViewControllerにドラッグ&ドロップしてセグエを作成します。セグエは以下のように設定してください。

続いて、追加したViewControllerの背景色をBlackにします。

もう一度Backgroundを選択して、「Other…」を選択します。

別ウィンドウが表示されるのでOpacityを50%にします。

この設定で、ハンバーガーボタンが設置されている遷移元の画面を透けて見えるようにします。

続いて、メニュー用のViewControllerを選択してPresentation欄でOver Current Contextを選択します。

 

次にUIViewを配置します。画面の左側に寄せて配置してください。ここがメニューの領域になります。

4.メニュー画面用のViewControllerクラスの作成

メニュー画面用のViewControllerクラスを作成します。

新規でファイルの追加をし、Cocoa Touch Classを選択します。

続いて、クラス名を「MenuViewController」にし、Subclass ofを「UIViewController」にしてファイルを作成します。

Storyboardでメニュー用のViewControllerを選択して、作成したMenuViewControllerクラスを設定します。

続いて、メニューのアウトレット接続を作成します。アウトレット接続名はmenuViewとします。

最後に、メニュー以外の領域を設定しておきます。メニュー以外の部分を選択して、Tagを1に設定します。メニュー領域外が選択されたかどうかは、このTagに設定した番号をコードから参照して「1」であれば非表示になるようにします。

5.メニュー表示/非表示のアニメーションコードを作成する

最後にメニューの表示/非表示のコードを作成します。このコードはメニュー画面用に作成したMenuViewController.swiftに記述します。

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    // メニューの位置を取得する
    let menuPos = self.menuView.layer.position
    // 初期位置を画面の外側にするため、メニューの幅の分だけマイナスする
    self.menuView.layer.position.x = -self.menuView.frame.width
    // 表示時のアニメーションを作成する
    UIView.animate(
        withDuration: 0.5,
        delay: 0,
        options: .curveEaseOut,
        animations: {
            self.menuView.layer.position.x = menuPos.x
    },
        completion: { bool in
    })
    
}

// メニューエリア以外タップ時の処理
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesEnded(touches, with: event)
    for touch in touches {
        if touch.view?.tag == 1 {
            UIView.animate(
                withDuration: 0.2,
                delay: 0,
                options: .curveEaseIn,
                animations: {
                    self.menuView.layer.position.x = -self.menuView.frame.width
            },
                completion: { bool in
                    self.dismiss(animated: true, completion: nil)
            }
            )
        }
    }
}

 

6.実行例

以上でハンバーガメニューの完成です。

実行例は以下の通りです。

 

[Tips]背景を透過させて遷移元のViewを見せるには?

はじめに

ViewControllerから別のViewControllerを呼び出した時に、Alertのように必要部分以外を透過させて見せたい場合があります。

今回は、背景を透過させる方法についてみていきます。

環境

Xcode:9.4.1
Swift:4.1.2

プロジェクトの作成

まずは、Single View Appのプロジェクトを作成します。

次に、Storyboardを開いて、ViewControllerにButtonを貼り付けます。

 

次に新しいViewControllerをstoryboardに配置します。

続いて、Buttonがタップされた時に追加したViewControllerに遷移するようにセグエを追加します。

セグエの種類は、ここではpresent Modallyにします。

続いて、遷移先のViewControllerの背景色を変更します。ここではBackgroundの欄でBlackを選択することとします。

もう一度 Background を選択して「Other…」を選択します。

別ウィンドウが表示されるので、Opacityを50%にします。ここのパーセンテージは透過率ですので、好みに合わせて調整してください。

さて、これだけでは背景が透けて見えるようにはなりません。

続いて遷移先のViewControllerを選択して(①)、Presentationに「Over Current Context」を選択します。

最後に、UIViewを配置して好きな色を設定します。

実行結果

実行をしてButtonをタップすると、画面は以下のようになります。遷移元のButtonが透けて見えていることが確認できます。

 

 

 

 

 

 

[Tips]Swiftのバージョンを確認するには?

Swiftのバージョンを調べるにはターミナルを使用します。

ターミナルを起動したら、コマンドラインで以下を入力します。

swift -v

このコマンドを実行すると、以下のようにバージョンを確認することができます。この場合はバージョンは4.1.2ということになります。

最後に以下の画面のように「1>」となり、入力待ちになります。

終了するには「:q」か「:exit」と入力します。

[Tips] 使用中のデバイスを判定するには?

環境

Xcode:9.2
Swift:4.0.3

使用中のデバイスを判定するには?

使用中のデバイスを判定するには、UIDevice.current.userInterfaceIdiomを使用します。

例えば、現在使用中のデバイスがiPadかを調べるには、以下のコードで調べることができます。

if UIDevice.current.userInterfaceIdiom  == .pad {

}

userInterfaceIdiomには以下のような値があります。

説明
phone iPhone
pad iPad
tv Apple TV
carPlay Car Play

FSCalendarを使用する(1) storyboardへの貼り付けと使用準備

今回は、FSCalenderを使用する方法を見ていきます。

FSCalenderの導入方法については前回の記事「CocoaPodsを使用してFSCalendarを導入する」を参照してください。

Single Viewアプリケーションのプロジェクトを作成して確認していきます。

FSCalendarの配置

はじめにMain.storyboardを表示して、UIViewを貼り付けます。

続いて、貼り付けたUIViewのClassを「FSCalendar」にします。

すると、先ほど貼り付けたUIVewにカレンダーが表示されるようになります。

続いてView ControllerにdataSourceとdelegateを設定します。

FSCalendar上で[control]キーを押しながら、View Controllerまでドラッグします。

ドラッグすると以下のようにOutlets作成用のウィンドウが表示されるので、dataSourceとdelegateを作成します(1回につき1つしか作成できないのでdataSourceとdelgate分の2回実行する必要があります)。

 

この時点で一旦ビルドをしておきましょう。

エラーが出ないことを確認するとともに、FSCalendarをインポートできるようになります。

続いてViewController.swiftを開き、コードを以下のように編集します。

FSCalendarをインポートし、FSCalendarDataSourceとFSCalendarDelegateを継承しています。

import UIKit
import FSCalendar


class ViewController: UIViewController,FSCalendarDataSource,FSCalendarDelegate {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

実行すると、以下のようにカレンダーが使用可能になります(カレンダーのサイズは任意で変更をしてください)。

 

CocoaPodsを使用してFSCalendarを導入する

iOSにはCalendarコントロールが提供されていないのですが、MITライセンスのFSCalendar(https://github.com/WenchaoD/FSCalendar/blob/master/README.md)というコントロールがあります。

今回は、CocoaPodsを使用して、このFSCalendarコントロールをプロジェクトに組み込む方法を見ていきます。

※CocoaPodsのインストール方法は「CocoaPodsの導入」を参照してください。

はじめに、新規でプロジェクトを作成しておきます。

次に、ターミナルを起動して、作成したプロジェクトディレクトリに移動して以下のコマンドを実行します。

pod init

成功するとプロジェクトディレクトリにPodfileが作成されます。

作成されたPodfileを開いて以下のように編集します。

# Uncomment the next line to define a global platform for your project
platform :ios, '9.0'

target 'WorkTimeManager' do
  # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
  use_frameworks!

  # Pods for WorkTimeManager
  pod 'FSCalendar', :git=> 'https://github.com/WenchaoD/FSCalendar'

end

Podfileの編集が完了したら、ターミナルに戻りPodfileがあるディレクトリ上で、以下のコマンドを実行してインストールをします。これによりプロジェクトにFSCalendarが取り込まれます。

pod install

ライブラリインストール完了移行は、以下のように「プロジェクト名.xcworkspace」をダブルクリックしてプロジェクトを開きます。

XcodeのProject Navigatorを確認するとFSCalendarが導入されていることを確認できます。

CocoaPodsの導入

Swiftでの開発を進めていくにあたり、ライブラリの導入は不可欠です。

CocoaPodsというライブラリ管理ツールがありますので、その導入方法を見ていきます。

はじめにCocoaPodsをインストールします。

ターミナルを開いて以下のようにコマンドを入力してインストールを行います。

sudo gem install cocoapods

続いて、以下のコマンドでセットアップをします。Setup Completedと表示されれば完了です。

pod setup

画像を表示する

今回は、ページに画像を表示する方法を見ていきます。

はじめに、新規でSingle Viewのプロジェクトを作成します。

プロジェクト名称はImageSampleとしました。

プロジェクトの作成が完了したら、Project NavigatorでAssets.xcassetsを選択します。

一般的にプロジェクトで使用する画像はAssets.xcassetsフォルダに格納して使用します。

Assets.xcassetsフォルダを選択すると、以下のような画面が表示されます。プロジェクトで使用したい画像をfinderからドラッグ&ドロップして登録します。

画像を登録すると以下のようになります。イメージは3種類登録しておくことができますが、とりあえず1つでOKです。また、登録した画像の名称は左側で変更することができますので、コードから参照する時の任意の名称にしておきます。ここではsampleという名称にしています。

画像を表示するコードの実装

画像の準備ができたら、あとは画像を表示するコードの実装のみです。

Project NavigatorでViewController.swiftを選択したら、コードを以下のように編集します。

import UIKit

class ViewController: UIViewController {

    // 画像インスタンス用
    let imageSample = UIImageView()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        // スクリーンサイズの取得
        let screenW:CGFloat = view.frame.size.width
        let screenH:CGFloat = view.frame.size.height
        
        // 画像を読み込んで、準備しておいたimageSampleに設定
        imageSample.image = UIImage(named: "sample")
        // 画像のフレームを設定
        imageSample.frame = CGRect(x:0, y:0, width:128, height:128)
        
        // 画像を中央に設定
        imageSample.center = CGPoint(x:screenW/2, y:screenH/2)
        
        // 設定した画像をスクリーンに表示する
        self.view.addSubview(imageSample)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

最初に、6行目で画像を入れる器(UIImageView)を準備しておきます。ここで準備したimageSampleに画像を読み込んだり、画像のフレームを設定したり、表示位置を設定したりして、最終的には画面(スクリーン)に表示します。

画像の読み込み〜表示までの処理はviewDidLoadの中で行います。

まずは、使用するデバイスのスクリーンサイズを取得しておきます(12,13行目)。このスクリーンサイズを使用して、後から画面の中央を計算するのに使用します。

続いて、画像を読み込みます(17行目)。画像を読み込む際は、Assets.xcassetsフォルダに登録した画像名を指定します。

画像の読み込みをしたら、表示サイズ(フレーム)を設定します(19行目)。

次に、画像がスクリーンの中央に表示されるようにします(22行目)。imageSample.centerは読み込んだ画像の中心です。この中心を、スクリーンの中央座標に合わせることで、画面中心に表示させます。

ここまでで、画像を中央に表示する準備は完了です。あとは25行目のようにしてassSubViewを実行することにより、画像が画面に表示されるようになります。

上記の実行例を以下に示します。