Swiftのカスタムクラスの作り方――プロトコル、サブクラス、イニシャライザー、タイププロパティメソッドのオーバーライド、デリゲートについて注釈の作成で学ぶ:iPhone 6/6 Plusアプリ開発入門(5)(4/4 ページ)
iPhone 6/6 PlusアプリをSwift言語で作成してみたいという初心者向けにiOS 8の新機能を使ったアプリの作り方を一から解説する入門連載。今回は、前回の記事で追加した地図上の「注釈」を写真のサムネイルに差し替える課程でSwiftのカスタムクラスの作成手順について解説します。
作成したカスタムオブジェクト/ビューを使う
カスタム注釈オブジェクト「PhotoAnnotation」とカスタム注釈ビュー「PhotoAnnotationView」の実装が完了しました。これらのオブジェクトを使用して注釈を地図上に表示するためにViewControllerを修正していきます。
デリゲート(delegate)の設定
ViewControllerの修正のメインの作業は、「mapView:viewForAnnotation:メソッドを追加し、注釈ビューのセットアップと更新処理を記述する」ことですが、そのためにはViewControllerがMapViewの「デリゲートオブジェクト」になる必要があります。
「デリゲート(移譲)」について、アップル公式のドキュメント「Objective-C プログラミングの概念」では以下のように説明されています。
デリゲート(delegate、委譲)とは、あるオブジェクトがプログラム中でイベントに遭遇したとき、それに代わって、または連携して処理するオブジェクトのことです。
ViewControllerがMapViewのデリゲートオブジェクトとなることで、「注釈ビューのセットアップ/更新」などの処理をViewControllerに任せることができます。
必要な作業は二つあります。
一つ目はMKMapViewDelegateプロトコルを採用することです。PhotoAnnotationの実装したときと同様にクラス名の後に採用したいプロトコル名を追加します。
... class ViewController: UIViewController, MKMapViewDelegate { // MKMapViewDelegateを追加 ... }
二つ目に必要なことはMKMapViewの「delegate」プロパティに「self」(ViewController自身)をセットすることです。selfをセットする1行をprepareMapViewメソッドに追加します(下記コードの4行目)。
private func prepareMapView() { self.mapView.rotateEnabled = false self.mapView.pitchEnabled = false self.mapView.delegate = self // 追加 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) }
注釈オブジェクト作成部分を修正
prepareAnnotationsメソッドを以下のように修正します。PhotoAnnotationを作成してMapViewに追加するように修正しています。
private func prepareAnnotations() { let fetchResult = PHAsset.fetchAssetsWithMediaType(PHAssetMediaType.Image, options: nil) fetchResult?.enumerateObjectsUsingBlock ({result, index, stop in if let asset = result as? PHAsset { if asset.location != nil { let annotation = PhotoAnnotation(asset: asset) self.mapView.addAnnotation(annotation) } } }) }
メイン作業――mapView:viewForAnnotation:メソッドを追加する
さて、いよいよ先の「今回の大まかな流れ」の2.と3.にあった「mapView:viewForAnnotation:」メソッドの追加です。mapView:viewForAnnotation:メソッドは注釈ビューが必要になったタイミングで呼ばれます。このメソッド内で行う主要な処理は以下の通りです。
- MKAnnotationViewの取得または作成(2〜8行目)
- PHImageManagerを使用して写真の実データを取得する(10〜28行目)
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! { let photoAnnotation = annotation as? PhotoAnnotation let photoAnnotationViewID = "photoAnnotationView" var photoAnnotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(photoAnnotationViewID) as? PhotoAnnotationView if photoAnnotationView == nil { photoAnnotationView = PhotoAnnotationView(annotation: photoAnnotation, reuseIdentifier: photoAnnotationViewID) } if let image = photoAnnotation?.image { photoAnnotationView?.image = image } else { let screenScale = UIScreen.mainScreen().scale let targetSize = CGSize( width: PhotoAnnotationView.size.width * screenScale, height: PhotoAnnotationView.size.height * screenScale) PHImageManager().requestImageForAsset( photoAnnotation?.asset, targetSize: targetSize, contentMode: .AspectFill, options: nil, resultHandler: {(image, info) -> Void in photoAnnotation?.image = image; photoAnnotationView?.thumbnailImage = image; } ) } return photoAnnotationView }
- MKAnnotationViewの取得または作成(2〜8行目)
4行目でMapViewのdequeueReusableAnnotationViewWithIdentifierメソッドを使用して未使用の注釈ビューの取得を試みています。
未使用の注釈ビューがなかった場合の処理は6〜8行目です。PhotoAnnotationViewに実装したイニシャライザーを使用して初期化を行っています。
- PHImageManagerを使用して写真の実データを取得する(10〜28行目)
photoAnnotationオブジェクトのimageプロパティがnilでなければphotoAnnotationViewのimageプロパティにセットします。
nilであれば、PHImageManagerのrequestImageForAssetメソッドを使用して写真の実データをリクエストし、引数のクロージャ内で、得られた画像データをphotoAnnotationとphotoAnnotationViewのプロパティにセットしています。
13〜16行目では、リクエストする画像データのサイズを作成しています。ポイント単位の大きさでそのままリクエストすると十分な大きさの画像が得られなかったので、PhotoAnnotationViewのsizeプロパティの値(44×44)に物理的なスクリーンのscaleを掛けたサイズ(iPhone 6やiPhone 5sなどであれば88×88、iPhone 6 Plusであれば132×132)のCGSizeを作成しています。
動作確認
[Run]ボタンをクリックしてiOSシミュレーターで動かしてみましょう。カスタムの注釈ビューが表示されます。
注釈ビューをタップすると、吹き出しが表示されます。
次回でPhotoMapアプリが完成
今回はカスタムの注釈オブジェクトと注釈ビューを新規作成し、地図上に写真のサムネイルが表示されるように修正しました。
次回は、注釈ビューが選択状態の場合に表示される吹き出しをタップした際の動きと、その時に表示される画面を作成します。次回で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/
Copyright © ITmedia, Inc. All Rights Reserved.
関連記事
- アプリは、どうやって動くの? プログラムって何?――初めて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アプリ開発に適用するためのツールやノウハウを解説する連載。