OptionalなどSwiftとObjective-Cの違いを意識してPhotos Frameworkを使う:iPhone 6/6 Plusアプリ開発入門(4)(3/3 ページ)
iPhone 6/6 PlusアプリをSwift言語で作成してみたいという初心者向けにiOS 8の新機能を使ったアプリの作り方を一から解説する入門連載。今回は、前回の記事で追加した写真の情報を「Photos Framework」の機能を使用して取り出し、写真の情報にひも付いた座標にピンを表示します。また、その過程でOptionalなどSwiftとObjective-Cの違いについて解説します。
MapViewに注釈オブジェクトを追加する
Optional型の説明が長くなってしまいましたが、ここで再びViewController.swiftファイルの実装に戻ります。
「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) } } }) }
Optional Chaining
3〜11行目の「fetchResult?.enumerateObjectsUsingBlock ({ ... })」では「Optional Chaining」を使用しています。「Optional Chaining」は「Optional型」や「Implicitly Unwrapped Optional型」の変数やメソッドに接尾辞「?」を付けて安全にアクセスできる仕組みです。
「Optional型」の変数に接尾辞「!」を付けて行うアンラップは、変数の内容にかかわらず中身を取り出すものでした。それに対し「Optional Chaining」は、変数が値を持つ場合は、その次の処理を継続し、変数の中身がnilの場合は処理を中断してnilを返します。
「prepareAnnotations」メソッド内の「fetchResult?.enumerateObjectsUsingBlock ({ ... })」の場合、fetchResultの中身がnilでない場合は、「enumerateObjectsUsingBlock」メソッドが実行され、fetchResultの中身がnilの場合は処理が終了します。
引数が「クロージャ」の「enumerateObjectsUsingBlock」メソッド
次に、PHFetchResultクラスのenumerateObjectsUsingBlockメソッドを見ていきます。
PHFetchResultオブジェクトは、フォトライブラリから取得した写真の情報を保持していて、enumerateObjectsUsingBlockメソッドを使用することで写真の情報を一つずつ取り出せます。
enumerateObjectsUsingBlockメソッドの定義は以下の通りです。
func enumerateObjectsUsingBlock(block: ((AnyObject!, Int, UnsafeMutablePointer<ObjCBool>) -> Void)!)
enumerateObjectsUsingBlockメソッドのblock引数は「クロージャ」になっています。クロージャは「値として扱える関数」のようなもので、メソッドの引数として渡すことができます。
enumerateObjectsUsingBlockメソッドに渡すクロージャ内には、写真情報一つを取り出した際に行う処理を記述しておきます。その処理は写真情報を取り出したときに実行されます。最終的に取り出せたデータ分の処理が行われます。
一つ目の引数resultに写真情報一つが入ってきます。resultの型はAnyObject!型(AnyObjectは任意のクラスのインスタンスを表す型)です。
クロージャ内のif文(4〜10行目)の条件式では、「型チェック」と「型キャスト」を行い「Optional Binding」を使用しています。最終的にPHAsset型のオブジェクトが取り出せた場合のみ真の処理が実行されます。
fetchResult?.enumerateObjectsUsingBlock ({result, index, stop in if let asset = result as? PHAsset { // PHAsset型のオブジェクトが取り出せた場合の処理 } })
注釈オブジェクトの作成
さらに内側のif文(5〜9行目)でも「Optional Binding」を使用しています。外側のif文で取り出したPHAsset型のオブジェクトから「CLLocation」型のオブジェクトを取り出し、注釈オブジェクトを作成して、MapViewへ追加しています。
これで、フォトライブラリから取得したPHAssetオブジェクトが保持する位置にピンが追加されます。
fetchResult?.enumerateObjectsUsingBlock ({result, index, stop in if let asset = result as? PHAsset { if let location = asset.location { // CLLocation型のオブジェクトが取り出せた場合の処理 // 注釈オブジェクトを作成 let annotation = MKPointAnnotation() annotation.coordinate = location.coordinate // MapViewへ追加 self.mapView.addAnnotation(annotation) } } })
ViewController.swiftの最終形
途中で寄り道してしまったので、ViewController.swiftの全コードを載せておきます。
本記事の内容を実装していくと、ViewController.swiftのコードは以下のようになります。
import UIKit import MapKit import Photos class ViewController: UIViewController { @IBOutlet weak var mapView: MKMapView! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. self.prepareMapView() self.checkAuthorizationStatus() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } private func prepareMapView() { self.mapView.rotateEnabled = false self.mapView.pitchEnabled = false let centerCoordinate = CLLocationCoordinate2D(latitude: 35.681382, longitude: 139.766084) let initialSpan = MKCoordinateSpan(latitudeDelta: 0.4, longitudeDelta: 0.4) let initialRegion = MKCoordinateRegion(center: centerCoordinate, span: initialSpan) self.mapView.setRegion(initialRegion, animated: true) } private func checkAuthorizationStatus() { let status = PHPhotoLibrary.authorizationStatus() switch status { case .Authorized: self.prepareAnnotations() default: PHPhotoLibrary.requestAuthorization{ status in if status == .Authorized { self.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) } } }) } }
動作確認
RunボタンをクリックしてiOSシミュレーターで動かしてみましょう。
初回起動時の場合、フォトライブラリへのアクセスの許可を求めるアラートが表示されるので、「OK」をクリックします。
アラートが消えると、MapView上にピンが追加されるはず……ですが、「注釈オブジェクトの追加」と「ピンの描画」のタイミングがちょっと合ってないみたいです。MapViewを任意の方向へスワイプさせて、MapViewの表示範囲を少し変更してみてください。
MapViewの中心位置が移動すると、ピンが描画されるかと思います(この不具合は今後修正しましょう)。
次回は、実際の写真の取得してピンと差し替える
今回は、前回の記事で追加した写真情報を「Photos Framework」の機能を使用して取り出し、写真情報にひも付いた座標にピンを表示しました。また、Swiftの特徴の一つである「Optional型」について解説しました。
次回も引き続き「PhotoMap」の実装を進めていきます。今回の記事で写真情報を基にピンを表示できたので、次回は実際の写真を取得し、標準のピンを写真のサムネイルに差し替えていきます。
- iOS 8アプリ開発のこれまで&Swift 1.2への対応、プロパティオブザーバーとwillSetの基本的な使い方、セグエを使った画面遷移
- Swiftのカスタムクラスの作り方――プロトコル、サブクラス、イニシャライザー、タイププロパティメソッドのオーバーライド、デリゲートについて注釈の作成で学ぶ
- OptionalなどSwiftとObjective-Cの違いを意識してPhotos Frameworkを使う
- Swiftでの変数の定義、Xcodeでのアウトレット接続、iOSシミュレーターへの画像素材追加
- iOS 8のPhotoKitの概要&Xcode 6.1/Storyboard/Auto Layout/iOSシミュレーターの基本的な使い方
- 開発者が知っておきたいiOS 8の新機能&Xcode 6のインストールと基本的な使い方
著者紹介
平屋真吾
クラスメソッド株式会社 iPhoneアプリサービス事業部所属のプログラマーです。iOSアプリの開発がメインですが、デザインやAWSなども勉強中です。
ブログ:http://dev.classmethod.jp/author/hiraya-shingo/
関連記事
- アプリは、どうやって動くの? プログラムって何?――初めて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.