連載
» 2015年04月07日 05時00分 公開

iPhone 6/6 Plusアプリ開発入門(5):Swiftのカスタムクラスの作り方――プロトコル、サブクラス、イニシャライザー、タイププロパティメソッドのオーバーライド、デリゲートについて注釈の作成で学ぶ (2/4)

[平屋真吾,クラスメソッド株式会社]

カスタムの注釈オブジェクト「PhotoAnnotation」を作成する

PhotoAnnotation.swiftファイルを追加する

 プロジェクトに「PhotoAnnotation.swift」ファイルを追加しましょう。[ナビゲータエリア]上の[PhotoMap]項目を右クリックして、出てきたメニューの[New File]を選択します。

図2 コンテキストメニュー

 テンプレート選択画面が表示されるので、[Cocoa Touch Class]を選択し、[Next]をクリックします。

図3 テンプレート選択画面

 追加するクラスのオプションについて以下のように入力し、[Next]をクリックします。

図4 オプション選択画面

 ファイルの保存先を選択します。以前の記事で作成した「ViewController.swift」ファイルと同じフォルダーを選択し、[Create]をクリックします。

図5 保存先選択画面

 これで「PhotoAnnotation.swift」ファイルがプロジェクトに追加されます。

図6 「PhotoAnnotation.swift」ファイル追加後の[ナビゲータエリア]

PhotoAnnotationクラスを実装する

 実装する内容は以下の通りです。順に説明していきます。

  1. import文(2〜3行目)
  2. MKAnnotationプロトコルを採用する(5行目)
  3. プロパティ定義(6〜13行目)
  4. イニシャライザー(15〜21行目)
  5. executeGeocodeメソッド(23〜38行目)
import UIKit
import MapKit
import Photos
 
class PhotoAnnotation: NSObject, MKAnnotation {
    var coordinate: CLLocationCoordinate2D
    var title: String?
    var subtitle: String?
    
    var address :String?
    var image :UIImage?
    
    let asset :PHAsset?
    
    init(asset aAsset:PHAsset) {
        asset = aAsset
        coordinate = aAsset.location.coordinate
        super.init()
        
        self.executeGeocode()
    }
    
    private func executeGeocode() {
        if let aAsset = self.asset {
            CLGeocoder().reverseGeocodeLocation(
                aAsset.location,
                completionHandler: {(placemarks, error) -> Void in
                    if error == nil && placemarks.count > 0 {
                        if let placemark = placemarks.first as? CLPlacemark {
                            self.title = placemark.name
                            self.subtitle = (placemark.administrativeArea ?? "") + (placemark.locality ?? "")
                            self.address = (self.subtitle ?? "") + (placemark.thoroughfare ?? "")
                        }
                    }
                }
            )
        }
    }
}
PhotoAnnotation.swiftファイルの内容
  • import文(2〜3行目)

 MapKitフレームワークとPhotosフレームワークをimportする記述を追加します。

  • プロトコルを採用する(5行目)

 任意のクラスを注釈オブジェクトとして使用するには、「MKAnnotation」プロトコルを採用する必要があります。

 「プロトコル」はメソッドやプロパティの宣言が集まったものです。例えば、MKAnnotationプロトコルの場合は、注釈オブジェクトが持つべきメソッドやプロパティが定義されています。プロトコルを採用するために必要なことは、「クラス名: 」の後に採用するプロトコル名を記述し、定義されたメソッドやプロパティを実装することです。

 プロトコルで定義されるメソッドやプロパティの中には、実装が任意のものと必須ものがあります。PhotoAnnotationクラスがMKAnnotationプロトコルを採用するに当たって実装が必須なのはcoordinateプロパティのみとなっています。

  • プロパティ定義(6〜13行目)

 6〜8行目の「coordinate」「title」「subtitle」プロパティは、MKAnnotationプロトコルで定義されているものです。「title」「subtitle」は値がnilになる場合があるので「String?」型にしています。

 10行目のaddressプロパティには撮影場所の住所を格納しておき、後に作成する詳細画面で使用します。11行目のimageプロパティには注釈ビューで使用するサムネイル画像のUIImageを格納します。

 address/imageプロパティに関しても値がnilになる場合があるので、それぞれ「String?」と「UIImage?」型にしています。

 13行目のassetプロパティにはフォトライブラリから取得した画像のPHAssetを格納します。

 次に説明するinitメソッド内で値を格納した後は値を再代入しないので定数にしています。型は「PHAsset?」です。

  • 指定イニシャライザー(15〜21行目)

 PhotoAnnotationクラスでは、引数がPHAsset1つのイニシャライザーを定義しています。

 15行目で定義しているイニシャライザーは「指定イニシャライザー」に分類されるイニシャライザーであり、そのクラスで定義している全てのプロパティに初期値を与えなければなりません。

 PhotoAnnotationクラス場合は、coordinate以外のプロパティはオプショナル型なので初期値は自動的にnilになります。ですので、最低限、coordinateプロパティに初期値を与えれば問題ありません。

 また、イニシャライザーの実装の中でスーパークラス(PhotoAnnotationの場合はNSObject)のイニシャライザーを呼ぶ必要がありますが、その前に全てのプロパティに初期値を与える必要があります。

 「スーパークラスで定義されているプロパティへの値の設定」や「selfを使ったアクセス」は、スーパークラスのイニシャライザーを呼んだ後であれば可能です。

 20行目で呼び出しているexecuteGeocodeメソッドについては次に説明します。

  • メソッド定義(23〜38行目)

 executeGeocodeメソッドでは、CLGeocoderreverseGeocodeLocationメソッドを使用して緯度経度データから住所文字列を作成しています。

  • nil結合演算子「??」

 31と32行目ではnil結合演算子「??」を使用しています。「??」の前の変数の値がnilでなければその変数の値が使われ、nilであれば「??」の後ろの値が使われます。

self.subtitle = (placemark.administrativeArea ?? "") + (placemark.locality ?? "")

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。