引き続き、ImageCell.swiftファイルに手を加えていきます。
以下のように「UIImage?」型の「assetImage」プロパティを追加し、このプロパティを介してクラス外から画像を設定するようにします(7〜10行目までを追加)。
import UIKit
class ImageCell: UITableViewCell {
@IBOutlet private weak var assetImageView: UIImageView!
// ここから
var assetImage :UIImage? {
willSet {
self.assetImageView.image = newValue
}
}
// ここまで追加
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
assetImageプロパティは格納型プロパティです。assetImageプロパティのコードブロック内の「willSet節」(willSet {...})は値が格納される直前に呼び出されます。
格納型プロパティの値が更新されるときに処理が行われる仕組みは「プロパティオブザーバー」と呼ばれ、willSet節以外にも、値が格納された直後に呼ばれる「didSet節」(didSet {...})があります。
ImageCellの実装例では、willSet節を使用して、画像オブジェクトをUIImageViewに設定しています。また、willSet節の仮引数を省略しているので、格納されようとしている新しい値は「newValue」という名前で取得できます。
以下のように仮引数を指定することもできます。
willSet (newImage) {
// 処理
self.assetImageView.image = newImage
}
ImageCell.swiftファイルの修正は以上で完了です。
Storyboadの編集に戻ります。Storyboard上の「Asset View Controller」の「ImageCell」を選択して、「Identifier」項目に「ImageCell」と入力します(図32)。
この「Identifier」はAssetViewControllerからCellを扱う際に使用します。
続いて、もう一方の「Address Cell」の設定を行います。「Address Cell」の修正はStoryboad上の操作で完結します。
「ImageCell」のと同様に「Identifier」の設定を行います。
Storyboard上の「Asset View Controller」の二つ目のセルを選択します(図33)。
「Identifier」項目に「AddressCell」と入力します(図34)。
最後に、「Address Cell」の左側のラベルにテキストを設定します(図35)。
Cellの実装は以上で完了です。
実装する内容は以下の通りです。順に説明していきます。
import UIKit
import Photos
class AssetViewController: UITableViewController {
var annotation :PhotoAnnotation?
// MARK: - Life cycle
override func viewDidLoad() {
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view delegate
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if indexPath.row == 0 {
return self.imageCellSize().height
} else {
return super.tableView(tableView, heightForRowAtIndexPath: indexPath)
}
}
override func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 0.01
}
// MARK: - Table view data source
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if let aAnnotation = self.annotation {
return 2
} else {
return 0
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCellWithIdentifier("ImageCell", forIndexPath: indexPath) as! ImageCell
let cellSize = self.imageCellSize()
if let aAnnotation = self.annotation {
PHImageManager().requestImageForAsset(
aAnnotation.asset,
targetSize: cellSize,
contentMode: .AspectFill,
options: nil,
resultHandler: {(aImage, info) -> Void in
if let image = aImage {
cell.assetImage = image
}
}
)
}
return cell
} else {
let cell = tableView.dequeueReusableCellWithIdentifier("AddressCell", forIndexPath: indexPath) as! UITableViewCell
cell.detailTextLabel?.text = self.annotation?.address
return cell
}
}
// MARK: - private
private func imageCellSize() -> CGSize {
if let annotation = self.annotation {
if let asset = annotation.asset {
let imageRatio = CGFloat(asset.pixelHeight) / CGFloat(asset.pixelWidth)
let cellWidth = self.tableView.bounds.size.width
let cellHeight = cellWidth * imageRatio + (1.0 / UIScreen.mainScreen().scale)
return CGSize(width: cellWidth, height: cellWidth * imageRatio)
}
}
return CGSizeZero
}
}
Photosフレームワークをimportする記述を追加します。
「PhotoAnnotation?」型の「annotation」プロパティを追加します。「PhotoAnnotation」は前回の記事で実装したクラスです。
AssetViewController.swiftファイル作成時に自動追加される「viewDidLoad」「didReceiveMemoryWarning」メソッドは、そのまま残します。修正箇所は、ありません。
8行目の「// MARK: - Life cycle」というコメントは、メソッドを種類ごとに分類するためのコメントで、AssetViewController.swiftファイルではメソッドの役割ごとに分類しています。このコメントを追加することによってXcodeのエディター上で、分類されたメソッドのリストを表示できるようになります(図36)。
UITableViewDelegateのメソッドを実装することによって「UITableViewのセルがタップされたときの処理」や「UITableView のセルやヘッダーの高さの指定」を記述できます。
27〜33行目の「tableView:heightForRowAtIndexPath:」メソッドはセルの高さを指定するためのメソッドです。0番目のセル(ImageCell)の場合は、後ほど説明する「imageCellSize」メソッドで計算した高さを返却します。0番目の以外のセル(AddressCell)場合は、スーパークラス(UITableViewController)の同名のメソッドで返却される値をそのまま返却します。
35〜37行目の「tableView:heightForHeaderInSection:」メソッドはセクションヘッダーの高さを指定するためのメソッドです。
UITableViewDelegateのメソッドを実装することによって「UITableViewの行の数」「UITableViewで使用するセルオブジェクト」などを指定できます。
41〜47行目の「tableView:numberOfRowsInSection:」メソッドでは「行の数」を返却します。
49〜75行目の「tableView:cellForRowAtIndexPath:」メソッドでは「セルオブジェクト」を返却します。
52行目と71行目で使用している「dequeueReusableCellWithIdentifier:forIndexPath:」メソッドは、引数で指定する「識別子」に関連したセルオブジェクトを取得するためのメソッドです。この「識別子」はStoryboard上で設定した「ImageCell」や「AddressCell」のことです。
MKMapViewが管理する注釈ビューと同様に、セルは必要に応じて使い回されます。「dequeueReusableCellWithIdentifier:forIndexPath:」メソッドを使用することで、セルの管理をUITableViewに任せることができます。
「imageCellSize」メソッドはImageCellのサイズを返却するメソッドです。セルのアスペクト比が写真のアスペクト比と等しくなるように計算して返却します。
アプリは、どうやって動くの? プログラムって何?――初めてiPhoneアプリを作る人向け基礎知識まとめ
iOSアプリにフォトショの機能などを組み込めるCreative SDKの基礎知識とインストール
iPhoneアプリで位置情報と地図を使うための基礎知識
開発者視点で見る、あのドデカい「iPhone 6/6 Plus」
【図解】Xcode 4.5の使い方リファレンス超まとめ
Android化が進むiOS 7の新機能と開発環境Xcode 5Copyright © ITmedia, Inc. All Rights Reserved.