ゼロから始めるiOSアプリ開発「iPhoneに保存されている画像を選んで表示するアプリ」
予備知識ゼロからiOSアプリを開発できるようにしよう!というのがこの「ゼロから始めるiOSアプリ開発」です。今回は「iPhone内の画像を選んで表示する」アプリを作ってみます。なお、この記事は公式の解説記事を参考にして作成しています。
Start Developing iOS Apps (Swift): Jump Right In
https://developer.apple.com/library/content/referencelibrary/GettingStarted/DevelopiOSAppsSwift/
第1回はストーリーボードの設定だけで画面遷移を実現しました。第3回となる今回も画面遷移を利用しますが、今回はコードを利用して画面遷移を実現してみます。
ゼロから始めるiOSアプリ開発「ボタンで画面を切り替えるアプリ」 - GIGAZINE
なお、前回の第2回は「コードを使って画面を操作する」という内容でした。
さっそく取り掛かっていきます。Xcodeを起動し、「Create a new Xcode project」をクリックして新しいプロジェクトを作成します。
「Single View App」が選択されていることを確認して「Next」をクリック。
今回はプロダクトネームを「selectImage」にしました。他の欄には前回の情報が残っているのでそのまま「Next」をクリックします。
保存先を確認して「Create」をクリックします。
UIパーツを配置していきます。前回は「Button」や「Label」を使用しましたが、今回使うのは「Image View」です。右下の欄から「Image View」をドラッグして画面に貼り付けます。
「Constraints(制約)」を使ってパーツの配置がずれないようにします。今回は両側の余白を32ポイントに設定し、さらにアスペクト比にも制約を設定します。制約を決めたら「Add 3 Constraints」をクリックします。
「Image View」の「Constraints」にある「aspect」の設定から「Multiplier」を「1:1」にしました。
下の画像のように、パーツの辺が赤くなっているのは、何らかの制約が足りておらずパーツの位置が一意には定まらないということを示しています。「Alignment Constraints」から画面の真ん中に配置されるように設定しました。
今配置したこのパーツをタップすることで画像を選ぶ画面に移動するようにしたいので、この「UIImageView」の上に「Tap Gesture Recognizer」をドラッグして配置します。
コードに取り掛かっていきます。右上の二重の輪になったマークをクリックして、アシスタントエディターモードに切り替えます。左にストーリーボード、右にコードという画面になります。
Ctrlキーを押しながらUIImageViewをクリックして、ドラッグしてコードに貼り付けます。
コードでの名前はなんでもよいのですが、今回は「imageView」としました。名付けたら「Connect」をクリックします。
続いて、画面の上に4つ並んでいるマークのうち右から2番目にある「Tap Gesture Recognizer」をCtrlを押しながらクリックしてコード画面にドラッグします。
「Connection」を「Action」に設定し、「Name」欄で名前を設定します。何でもよいのですが今回は「selectImage」としました。続いて「Type」の右にあるメニューから、「UITapGestureRecogni...」を選択します。最後に「Connect」をクリック。
UIImageViewがタップされると下の画像の「//UIImageViewがタップされた時の動作を記述していく」の部分が実行されます。
画像を選択するためには「画像を選択するための画面」を用意する必要があります。もっとも、Appleが「画像を選択するための画面」専用のクラスを用意してくれているため、難しいことは考えずにそのクラスを利用していきます。まず、
let pickerController
として新しい画面を「pickerController」と名付けます。この名前は何でも大丈夫です。続いて
let pickerController = uiimagepi
まで入力すると候補が下に出てくるので「UIImagePickerController」を選択してエンターキーを押します。そして、画面の実体であるインスタンスを得るために最後に「()」を書き加えます。クラスとインスタンスの関係については@komo_taさんによるQiitaへの投稿などが分かりやすいです。
画像を「フォトライブラリ」から選択できるように設定していきます。先ほど作成した画面を名前通りに「pickerController」と入力し……
ドット「.」でつないで「sourceType」と入力します。
その後、「=」と入力してもう一度「.」を入力すると候補が3つ表示されます。「camera(カメラで撮影)」「photoLibrary(フォトライブラリ)」「savedPhotosAlbum(フォトアルバム)」から選択できるのですが、今回は「フォトライブラリ」を選択。
続いて、「画像選択の画面を操作するためのコードをどこに書くか」を設定します。標準で用意されている画像選択画面クラスの「UIImagePickerController」には「delegate」という仕組みがあり、「必要最低限のことだけ書けば良い」という便利な仕様になっています。使用するには、まず「pickerController.delegate」と入力し……
その後ろに「= self」と書けばOK。今回のこの「self」は今コードを書いている「ViewController」クラスを指しているので、あとで「ViewController」内に「画像選択の画面を操作するためのコード」を書いていきます。
「delegate」を使うためにはそれぞれのデリゲートプロトコルを適用しておく必要があります。と言っても難しいことはなく、単にコードの一番上にある「class ViewController: UIViewController」の後ろにデリゲートプロトコルの名前を書いておくだけです。
UIViewControllerの後ろをカンマ「,」で区切り、その後ろに「UIImagePickerControllerDelegate」と入力します。
同じ要領で「UINavigationControllerDelegate」と加えていきます。どのデリゲートプロトコルを加えればよいのかは公式のドキュメントなどで確認できます。
なお、エディタの表示領域の都合で改行して表示される場合がありますが、左端の行番号が1つであれば大丈夫です。
さて、「UIImageViewがタップされた場合の処理」の部分に戻ってきて、最後に「画像選択画面を表示する」という処理を書いていきます。「present」と入力して出てくる「present(viewControllerToPreset...)」を選択してエンターキーを押します。
すると自動的に画面遷移のコードのひな形が入力されます。viewControllerToPresentには用意した画面の名前を入力します。今回は「pickerController」と入力しました。
「animated:」は画面の移動時にアニメーションを行うかどうかで、今回は「true」を選択。「false」にすると一瞬で画面が切り替わります。「completion:」は画面の移動後に行う処理を記述します。今回はなにも行わなくて良いので「nil」と入力しました。
先ほどpickerControllerのdelegateを「self」に設定したので、ViewController内に画像選択画面の動作を記述していきます。といっても定めるべき動作は2つだけで、一つは「何らかの理由で画像選択がキャンセルされた時の動作」、もう一つは「画像が選択された時の動作」です。まずはキャンセル側を作っていきます。「func ima」と入力して出てくる「imagePickerControllerDidCancel~」を選択します。
自動でコードが入力されます。間に表れる「code」という部分にコードを書いていきます。
キャンセルされた場合、画像選択画面を閉じるだけで良いので「dismiss~」を選択します。
dismiss()は「今の画面を閉じる」という働きをします。「animated:」には「true」、「completion:」には「nil」を設定しました。
今度は画像が選択された場合の動作を記述していきます。「func imagedidfinish」と入力し、出てきた「imagePickerController~」を選択します。
コードが自動で入力されます。青く表示されている「code」の部分に「画面が選択された場合の動作」を書いていきます。
今回はエラーでフリーズした時に原因を明らかにするために、Guard-Let構文を使用します。詳しくは次回以降に説明するので、「そういうのもあるんだ」程度に見ておいて下さい。「guardlet」と入力するとサジェストされる「guardlet - Swift Guard-Let Statement」を選択し、エンターキーを押します。
すると自動でコードが入力されます。
新しい変数「selectedImage」を用意して、そこに画像が代入できるかどうかを調べ、できなければエラーを返すという文にします。「=」の左側は新しい変数名なので何でも大丈夫ですが、右側の「info」は上の引数から来ているので「info」と書く必要があります。
「info」は辞書型配列で渡されます。目的の画像は「UIImagePicker~」という部分に格納されているので、infoの後ろに「uiimageorigin」と入力してサジェストされた「UIImagePicker~」を選択した後、[ ]で囲います。
elseの後ろはselectedImageへの代入が失敗した場合に呼び出されます。「return」を削除して、代わりに「fatalError」を挿入します。
エラー文を書き込みます。その下で、画面に配置した画像表示UIのimageViewにselectedImageを代入しようとしたのですが、エラーが返ってきてしまいました。
selectedImageの型をUIImageにできていなかったのが原因だったようなので、上のGuard-Let文の後ろに「as? UIImage」と追加。
最後にキャンセルの処理と同じように画像選択画面を「dismiss」で閉じればアプリ完成です。
シミュレータの画面が大きすぎないように「iPhone SE」を選択し、実行ボタンを押します。
アプリが立ち上がったのですが真っ白です。これではどこをタップすればいいのかが全く分かりません。
背景色を選択していなかったのが原因でした。画面に貼り付けられた「ImageView」を選択し、右の設定欄から「Background」の色を選択します。
もう一度実行してみると、タップするべき場所が分かるようになりましたが、タップしてみても全然反応がありません。
どんなパーツでも、ユーザーからのアクションを受け取るには「User Interaction Enabled」にチェックを入れる必要がある、ということを失念していました。もう一度「ImageView」を選択し、「Background」のやや上にある「User Interaction Enabled」にチェックを入れて再度実行します。
緑の部分をタップすると……
画像選択画面が下から出てきました。「Camera Roll」を選択してみます。
シミュレータに標準で用意されている画像が表示されました。左下の滝の画像をタップしてみると……
最初の画面にフォトライブラリから選択した滝の画像が表示されました。
「クラス&インスタンス」や「delegate」など、初めての人には難しい概念が出てきました。クラスとインスタンスはオブジェクト指向の言語にほぼ共通の概念なので、他の言語での説明でも理解の助けになります。「delegate」については、既存の設計を利用するだけならあまり理解していなくても実装できるので、まずは触ってみて、なんとなく「delegate」というものをつかんでから詳しい解説を読んでみた方が理解しやすいと思われます。
・つづき
ゼロから始めるiOSアプリ開発「作ったアプリをiPhoneにインストールしてみよう」 - GIGAZINE
・関連記事
Amazonがトラック業界の構造を一変させる可能性のある新アプリを開発、2017年夏にもリリース予定 - GIGAZINE
プログラマーたちが使った開発ツール2016年トップ50のランキング「Top 50 Developer Tools of 2016」をStackShareが発表 - GIGAZINE
図解・どっちが勝ち組?ウェブデザイナーVSデベロッパー編 - GIGAZINE
「給料が多いほど仕事が好き」「よく使うプログラミング言語」「開発環境」「開発者歴」「OS」など世界中の開発者の統計をまとめた「Stack Overflow Developer Survey 2016」 - GIGAZINE
「生涯現役開発者」を貫く40代~60代のソフトウェア開発者たち - GIGAZINE
・関連コンテンツ