Xcode 6.0の時点ではバージョン1.0だったSwiftですが、Xcode 6.3のリリースと共にバージョン 1.2になりました。Swift 1.2の改善点や修正点は以下のSwiftの公式ブログで説明されています。
「PhotoMap」アプリの実装に関係するSwift 1.2の変更は以下の2点です。この変更に関わる部分を修正しましょう。
プロジェクトファイル(PhotoMap.xcodeprojファイル)を開きビルド([command]+[B]キー)を行ってください。図2のように、PhotoAnnotationViewクラスのコードが原因でビルドが失敗すると思います。
エラーメッセージは以下の通りです。
'AnyObject' is not convertible to 'UIView'; did you mean to use 'as!' to force downcast?
「AnyObjectはUIViewに変換できない」という内容のエラーメッセージです。
override init(annotation: MKAnnotation!, reuseIdentifier: String!) { super.init(annotation: annotation, reuseIdentifier: reuseIdentifier) self.frame = CGRect(origin: self.frame.origin, size: PhotoAnnotationView.size) self.canShowCallout = true self.rightCalloutAccessoryView = UIButton.buttonWithType(.DetailDisclosure) as UIView // エラー箇所 self.thumbnailImageView = UIImageView(frame: CGRect(origin: CGPointZero, size: PhotoAnnotationView.size)) self.thumbnailImageView.contentMode = .ScaleAspectFill self.thumbnailImageView.clipsToBounds = true self.addSubview(self.thumbnailImageView) }
PhotoAnnotationViewクラスのinitメソッド(引数:annotation、reuseIdentifier)で使用している「UIButton」の「buttonWithType」メソッド(7行目)の返却値は「AnyObject」型です。
「AnyObject」型は任意のクラスのインスタンスを表す型であり、Objective-Cのクラスのメソッドの返却値の型などで使われています。「UIButton」といった具体的な型を与えて変換を行うことにより、変換後の型のオブジェクトとして動作させることができます。
これまでは「as」演算子を使用してダウンキャスト(抽象度の高い型から具体的な型への型変換)を行っていましたが、Swift 1.2以降では「as!」演算子を使用してダウンキャストを行う必要があります。以下のように「as!」演算子を使用した記述(7行目)に変更しましょう。
override init(annotation: MKAnnotation!, reuseIdentifier: String!) { super.init(annotation: annotation, reuseIdentifier: reuseIdentifier) self.frame = CGRect(origin: self.frame.origin, size: PhotoAnnotationView.size) self.canShowCallout = true self.rightCalloutAccessoryView = UIButton.buttonWithType(.DetailDisclosure) as! UIView // 修正箇所 self.thumbnailImageView = UIImageView(frame: CGRect(origin: CGPointZero, size: PhotoAnnotationView.size)) self.thumbnailImageView.contentMode = .ScaleAspectFill self.thumbnailImageView.clipsToBounds = true self.addSubview(self.thumbnailImageView) }
修正後、再びビルドを行うとダウンキャストを行っている行のエラーは消えると思います。別のエラーが表示されますが、これは次のセクションで修正します。
「ダウンキャスト」部分を変更しても、ビルドは失敗してしまい、エラーの指摘がさらに増えるかと思います(図3)。
指摘部分を修正してしまいましょう。表示されているエラーメッセージは以下の2種類です。
Immutable value 'self.thumbnailImageView' may only be initialized once
Property 'self.thumbnailImageView' not initialized at super.init call
「thumbnailImageViewは複数回初期化できない」「thumbnailImageViewはスーパークラスのイニシャライザーを呼ぶ前に初期化されていない」といった内容の指摘です。
private let thumbnailImageView: UIImageView! // オプショナル型なので初期値nilがセットされる override init(annotation: MKAnnotation!, reuseIdentifier: String!) { super.init(annotation: annotation, reuseIdentifier: reuseIdentifier) self.frame = CGRect(origin: self.frame.origin, size: PhotoAnnotationView.size) self.canShowCallout = true self.rightCalloutAccessoryView = UIButton.buttonWithType(.DetailDisclosure) as! UIView self.thumbnailImageView = UIImageView(frame: CGRect(origin: CGPointZero, size: PhotoAnnotationView.size)) // 定数への代入 self.thumbnailImageView.contentMode = .ScaleAspectFill self.thumbnailImageView.clipsToBounds = true self.addSubview(self.thumbnailImageView) }
PhotoAnnotationViewクラスのinitメソッドの例では、以下のようにthumbnailImageView定数に2回値を設定していました。
このように、定数へ値を与えるタイミングは2回存在していましたが、Swift 1.2からは1回に制限されます。
thumbnailImageViewプロパティはUIImageView!型のままにしておきたいので、定数定義時に初期値を設定するようにして、イニシャライザー内での値の代入は削除します。
修正後のコードは以下の通りです。
private let thumbnailImageView: UIImageView! = UIImageView(frame: CGRect(origin: CGPointZero, size: PhotoAnnotationView.size)) override init(annotation: MKAnnotation!, reuseIdentifier: String!) { super.init(annotation: annotation, reuseIdentifier: reuseIdentifier) self.frame = CGRect(origin: self.frame.origin, size: PhotoAnnotationView.size) self.canShowCallout = true self.rightCalloutAccessoryView = UIButton.buttonWithType(.DetailDisclosure) as! UIView self.thumbnailImageView.contentMode = .ScaleAspectFill self.thumbnailImageView.clipsToBounds = true self.addSubview(self.thumbnailImageView) }
ここまでの修正を終えると、エラー表示は消えると思います。次ページからは、「詳細画面」を実装していきましょう。
Copyright © ITmedia, Inc. All Rights Reserved.