OptionalなどSwiftとObjective-Cの違いを意識してPhotos Frameworkを使う:iPhone 6/6 Plusアプリ開発入門(4)(2/3 ページ)
iPhone 6/6 PlusアプリをSwift言語で作成してみたいという初心者向けにiOS 8の新機能を使ったアプリの作り方を一から解説する入門連載。今回は、前回の記事で追加した写真の情報を「Photos Framework」の機能を使用して取り出し、写真の情報にひも付いた座標にピンを表示します。また、その過程でOptionalなどSwiftとObjective-Cの違いについて解説します。
Swiftにおけるswitch文
「checkAuthorizationStatus」メソッド内では、switch文を使用して処理を分岐させています。「Swiftにおけるswitch文」と「C言語やObjective-Cのswitch文」を比較すると、以下のような点が異なっています。
- case文の最後に「break」を記述する必要がない
- 整数値だけではなく、文字列や構造体なども扱える
- case文に指定可能な条件が増えた
- 値を全て網羅する必要がある
Swiftにおけるif文
if文についても「Swift」と「C言語やObjective-C」の違いを比較してみます。異なる部分は以下の通りです。
- 条件式の( )を省略可能
- 条件式の後の{ }は省略できない
- 条件式の評価後の値がBool型でなければならない
次に、フォトライブラリから写真の情報を取得し、写真に付随する位置情報を使ってMapViewにピンを立てます。
フォトライブラリから全ての写真のPHAssetオブジェクトを取得する
先ほど登場した「prepareAnnotations」メソッドの内容は以下の通りです。
private func prepareAnnotations() { let fetchResult = PHAsset.fetchAssetsWithMediaType(PHAssetMediaType.Image, options: nil) fetchResult?.enumerateObjectsUsingBlock ({result, index, stop in if let asset = result as? PHAsset { if let location = asset.location { let annotation = MKPointAnnotation() annotation.coordinate = location.coordinate self.mapView.addAnnotation(annotation) } } }) }
それぞれの行を見ていきましょう。
2行目で「PHAsset」クラスの「fetchAssetsWithMediaType」メソッドを使用するとメディアタイプを指定してPHAssetオブジェクトを取得できます。
fetchAssetsWithMediaTypeメソッドの定義は以下の通りです。
class func fetchAssetsWithMediaType(_ mediaType: PHAssetMediaType, options options: PHFetchOptions!) -> PHFetchResult!
本連載一回目の記事「開発者が知っておきたいiOS 8の新機能&Xcode 6のインストールと基本的な使い方」でも説明しましたが、PHAssetはフォトライブラリ内の写真のメタデータを保持するオブジェクトです。また、メディアタイプは「PHAssetMediaTypeImage(写真)」を指定しています。
let fetchResult = PHAsset.fetchAssetsWithMediaType(PHAssetMediaType.Image, options: nil)
Swiftの特徴の一つ「Optional型」とは
ここで、Swiftの特徴の一つである「Optional型」について説明しましょう。
本記事で扱うクラスに関連する「Optional型」
PHAssetクラスの「fetchAssetsWithMediaType」メソッドの定義を再度確認してみます。戻り値の型が「PHFetchResult!」となっており、「PHFetchResult」という型名に接尾辞「!」が付いています。
class func fetchAssetsWithMediaType(_ mediaType: PHAssetMediaType, options options: PHFetchOptions!) -> PHFetchResult!
また、UIViewControllerクラスの「title」プロパティの定義を確認すると、型が「String?」となっており、「String」という型名に接尾辞「?」が付いています。
var title: String?
Optional型とは
Optional型は、以下の二つの状態を採り得る型で、「値がないかもしれない状況」で使用します。
- 整数値や文字列などの値を持つ状態
- 値を持たない状態
例として、UIViewControllerクラスの「title」プロパティを見てみます。「title」プロパティは「String?型」であり、「String?型」は「Optional<String>型」のシンタックスシュガー(すでに定義されている他の構文の書き換え)です。
var title: String?
String型として宣言された変数は文字列以外の値を保持できませんが、String?型として宣言された変数は文字列以外にnilを値とすることができます。nilを値とすることで「値を持たない状態」を表します。
var name : String = "Taro" var title : String? = "Hello Swift" name = nil // エラーになる title = nil // 代入可能
また、型名に接尾辞「?」を付与して、nilを代入可能にすることを「Optional型でラップする」と呼びます
例としてString型について説明しましたが、他の型でもOptional型でラップすることによってnilが代入可能になります。プリミティブ値を保持するInt型もラップすることができ、Int?型には数値の他にnilを代入することができます。
Objective-Cとの比較
「Optional型」はObjective-Cにはなかったコンセプトです。Objective-Cの場合、nilを使用して「値がない状態」を表せます。しかし、これはオブジェクト型に限定したものです。オブジェクト型でない型の場合は「値がない状態」を表す例として、「NSNotFound」などの定数を使用することが挙げられます。
このようにObjective-Cでは、「値がない状態」の表し方は型ごとに異なっており、使い方によっては想定外の動きが発生して問題になってしまいます。Swiftでは「Optional型」を使用することで、このような問題を解決できます。
Optional型のアンラップ
自動的にOptional型に変換されるため、Optional型の変数に通常の型の変数を代入することは可能です。
var title : String? = "Hello Swift"
逆に、通常の型にOptional型の変数を代入することはできません。Optional型の変数はnilを持つ可能性があり、通常の型にnilを代入できないからです。
var title : String? = "Hello Swift" var name : String = title // エラーになる
Optional型の変数を通常の型に代入するには、Optional型でラップされた変数を「アンラップ」する必要があります。アンラップするには、以下のように変数に接尾辞「!」を付けます。
var title : String? = "Hello Swift" var name : String = title!
アンラップは、変数の内容にかかわらず中身を取り出します。Optional型の変数を通常の型に代入する場合、「!」を使ってアンラップを行う前に、Optional型の変数の値がnilではないことを確認する必要があります。nilに対してアンラップを行うと、ランタイムエラーになってしまいます。
var title : String? = "Hello Swift" var name : String if title != nil { // nilチェック name = title! // アンラップ print("name is \(name)") }
Optional Binding
「アンラップを行う前に、Optional型の変数の値がnilではないことを確認する必要がある」と説明しましたが、「Optional Binding」という方法を使えば、もう少し簡潔に記述できます。
「Optional Binding」はif文やwhile文を使って記述できます。if文を使用する場合のOptional Bindingの形式は以下の通りです。
まず、条件式右辺のOptional型変数のnilチェックが行われます。変数が値を持つ場合は、アンラップされて左辺の定数に代入され、if文の真の処理が実行されます。それ以外の場合は、偽の処理が行われます。
if let 定数名 = Optional型の変数名 { // 処理 }
以下に例を示します。変数titleは値を持っているので、titleはアンラップされて定数nameに代入され、真の処理が実行されます
var title : String? = "Hello Swift" if let name = title { // Optional Binding print("name is \(name)") }
Implicitly Unwrapped Optional型
ここまで「Optional型」について説明しましたが、「Implicitly Unwrapped Optional型」もnilを値とすることができる型です。
ここで再びPHAssetクラスのfetchAssetsWithMediaTypeメソッドの定義を見てみましょう。
class func fetchAssetsWithMediaType(_ mediaType: PHAssetMediaType, options options: PHFetchOptions!) -> PHFetchResult!
fetchAssetsWithMediaTypeメソッドの戻り値の型は「PHFetchResult!型」であり、「PHFetchResult!型」は「ImplicitlyUnwrappedOptional<PHFetchResult>型」のシンタックスシュガーです。
Implicitly Unwrapped Optional型はその名の通り「暗黙のうちにアンラップするOptional型」であり、「Optional型」と違って、アンラップすることなく内包された値にアクセスできます。
関連記事
- アプリは、どうやって動くの? プログラムって何?――初めてiPhoneアプリを作る人向け基礎知識まとめ
本連載では、これからプログラミングやiPhoneアプリ開発を始めてみたい方を対象に、開発に必要な知識を基礎から解説していきます。 - iOSアプリにフォトショの機能などを組み込めるCreative SDKの基礎知識とインストール
Photoshopのような写真編集や動画編集、ユーザー管理、描画用デバイス連携などの機能をアプリに追加できるSDKについて概要とインストール方法を解説する。 - iPhoneアプリで位置情報と地図を使うための基礎知識
利用が加速するジオメディアを使うための基礎としてCoreLocationとMapKitの2つのフレームワークの使い方を中心に解説します。 - 開発者視点で見る、あのドデカい「iPhone 6/6 Plus」
開発者は新iPhoneの画面サイズに合わせ、UI全てを作り直さないといけないの? アプリ開発者でもある筆者が、その現状を調べてみた。 - 【図解】Xcode 4.5の使い方リファレンス超まとめ
Windowsを使っていたけど、iOSアプリを作るためにMacを使い始めた初心者を対象に、開発ツールXcode/iOS SDKを使ってiPhone/iPadアプリを作る方法を、プログラミング言語「Objective-C」の書き方/文法を交えて解説。今回は、iPhone/iPadアプリ開発に必要なiOS SDKの概要や標準開発ツール「Xcode」の画面構成を紹介。iOS SDKはInterface BuilderやInstrumentsなど便利なツールを備えています - Android化が進むiOS 7の新機能と開発環境Xcode 5
大きく変化したiOS 7に戸惑う多くの開発者/デザイナのために、役立つブログ記事をまとめて紹介していく、まとめ連載。初回は開発者/デザイナから見たiOS 7の新機能8選と開発環境「Xcode 5」と開発環境構築について。 - Cocoaの素、Objective-Cを知ろう
iPhone用アプリケーション開発で注目を集める言語「Objective-C」。C++とは異なるC言語の拡張を目指したこの言語の基本を理解しよう。 - 生産性ガチアゲなオープンソースiOSライブラリ
ゼロからiOS SDK開発を始める新規開発者でも超高速・高品質な開発を可能にするオープンソースのライブラリを目的別に紹介していく連載です。実際にライブラリを組み込みながら技術的な側面も併せて詳細に説明していきます。 - iOSアプリ開発でもCI/継続的デリバリしようぜ
現代の開発現場において欠かせないCI/継続的デリバリを、iOSアプリ開発に適用するためのツールやノウハウを解説する連載。
Copyright © ITmedia, Inc. All Rights Reserved.