【Apple Watchでできること】まとめ

WordPressブログをiPhoneネイティブアプリ化(AppleWatch対応版)のチュートリアル 第2回「テーブルビューに情報を表示する」

AWJ tutorial

WordPressを使っているサイトのネイティブアプリ化(AppleWatch対応版)のチュートリアル第2回目です。
(第1回はこちら→第1回「HTTP通信でブログのデータを取得する」

作るのはこんなアプリ

アプリ版AppleWatchJournalをそのまま作成します。
詳しい動作は実際のアプリを参照ください!

AWJ

無料
(2015.08.14時点)
posted with ポチレバ

※そして、もしよかったらAppleWatchJournalも定期的にチェックしていただけますと超幸いです。よろしくです。

ナビゲーションバーを作る

Navigation Controllerを設置する

「Main.storyboard」を選択。
View Controller SceneのView Controller(黄色い四角のアイコン)を選択した状態で、メニューのEditor > Embed In > Navigation Controllerを選択。
20150814083950

キャンバス上にNavigation Controllerが追加されます。
20150814085204

Navigation Controllerにタイトルを設定

ナビゲーションに表示するタイトルを設定します。
ViewController.swiftのviewDidLoadメソッドでtitleプロパティを使って設定します。

override func viewDidLoad() {
  super.viewDidLoad()
  self.title = "AWJ" //ViewControllerのタイトル設定

IMG 7763

Navigation Controllerの色を設定

Navigation ControllerのNavigation Barを選択。
Attributes Inspectorの「Bar Tint」で好きな色を選択します。
20150814092647

ただし、選択した色によっては、タイトルやステータスバーの色が「黒」なのが読み難い場合があります。
IMG 7764

そういう場合はタイトルの色も変更した方がいいでしょう。
ステータスバーの色は基本的に「黒」か「白」しか選べないので、タイトルもそれに合わせて「黒」か「白」にしておくと無難なデザインにまとまると思います。

タイトルの文字色を変更

ナビゲーションバーの背景色と同様に、Navigation ControllerのNavigation Barを選択→Attributes InspectorのText Colorを白に変更します。
20150814094104

ステータスバーの文字色を変更

Supporting Filesの「Info.plist」に以下のステータスを追加します。
20150814095259
・View controller-based status bar:NO
・Status bar style:UIStatusBarStyleLightContent
※「UIStatusBarStyleLightContent」は選択メニューに出てこないので、直接文字列として入力してください。

これで、ナビゲーションバーの色設定は完了です!
IMG 7765

メインページを作成する

続いて、Main.storyboardでメインページを作成していきましょう。

Table Viewを配置する

Object LibraryからTable Viewを選択、View Controllerにドラッグ&ドロップ。
20150814222404
ドラッグすると中心線を表すグリッドが表示されるので、上下左右の中心位置にドロップしましょう。

Table Viewを選択した状態で、画面右下の「Resolve Auto Layout Issues」から「Add Missing Constraints」をクリック。
20150814223205
様々なサイズのiPhoneでいい感じに表示されるように、レイアウト設定に必要な数値を自動で入力してくれます。
(この辺りのUIの作り方は正直まだよくわかってないところもありまして…。こんな本を買ってお勉強中です↓)

Attributes InspectorでPrototype Cellsを「0」から「1」に変更。
20150815074439

Size InspectorでRow Heightを「100」に変更。
20150815075635

Table Viewを選択した状態で、Connections InspectorのOutletsエリアで、datasourceの横の○をView Controllerにドラッグ&ドロップして、接続します。
同様に、delegateもView Controllerに接続します。
20150815092114

最後に、Attribute InspectorのIdentifierに任意の名前をつけます。今回はわかりやすく「Cell」としました。
20150815120549

Table View Cellを作成する

Object LibraryからImage Viewを選択、Table View Cellにドラッグ&ドロップします。
20150815080052

画面左端に表示されるように、Size Inspectorで位置とサイズを変更。
20150815080357

ViewのModeを「Redraw」に変更。(サイズに対する画像のフィット方式を変更しています。)
20150815123005

同じように、「Label」を3つ、Tabele View Cellにドラッグ&ドロップします。
20150815080710

Size Inspectorを使って、いい感じに配置します。
(この辺りのUIの作り方は正直まだよくわかってないところも(ry…
20150815090711
このあたりは、あとで実際にデータを表示した状態で、実機で動かしながら微調整した方が良いかもしれません。

それぞれのLabelに対して、Attribute Inspectorでフォントサイズ・色・行数などを指定します。
20150815091431
上から
・「Color: #000000」「Font: System 16.0」「Lines: 2」
・「Color: #BC204D」「Font: System 13.0」「Lines: 1」※Navigation Barに合わせた配色がオススメです。
・「Color: #C4C4B8」「Font: System 13.0」「Lines: 1」

フォントの種類や色など、サイトのイメージに合わせて、いい感じに調整してみてください!(雑!)

Custom Cellクラスの作成

Project navigatorの右クリックメニューの「New File…」、または上部メニューの「File > New > File…」
20150815092839

「Cocoa Class」を選択。
20150815092846

クラス名は適当に。Subclass ofは「UITableViewCell」を選択してください。
20150815092906

ファイルの保存場所を指定(デフォルトのままでOKです)して、「Create」をクリック。
20150815092915

Custom Cellクラスとstoryboardを接続

Main.storyboardに戻り、Table View Cellを選択した状態で、Identify InspectorのCustom Classで、先ほど作成した「CustomCellクラス」をClassに指定します。
20150815094356

さらに、TableViewCellを構成しているImage ViewとLabelを、CustomCellにOutlet接続します。
20150815095111

接続する際の「Name」プロパティは、それぞれ、thumbnail, title, category, dateと指定しています。
CustomCellクラスは、以下のようになっていると思います。

import UIKit

class CustomCell: UITableViewCell {
  @IBOutlet weak var thumbnail: UIImageView!
  @IBOutlet weak var title: UILabel!
  @IBOutlet weak var category: UILabel!
  @IBOutlet weak var date: UILabel!  
}

UITableViewを実装する

まずはTable ViewをViewController.swiftにOutlet接続します。
20150815113523

続いて、ViewController.swiftにTableViewを使うためのプロトコルを適合します。
ついでに、テーブルに表示するthumbnail画像をキャッシュするための変数を定義しておきます。

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
  @IBOutlet weak var table: UITableView!
  var entryDataArray = NSArray() // entriesデータを格納する配列
  var imageCache = [String:UIImage]() //thumbnail用のimageCache

※この時点でエラーが出ますが、今は気にしないで開発を進めましょう。

viewDidLoadメソッドの中で、datasourceと、delegateを指定します。
Datasourceの参照先の指定、セルをタップした時のdelegate先は、それぞれViewControllerで定義するので、どちらも参照先はselfになります。

override func viewDidLoad() {
  super.viewDidLoad()

  self.title = "AWJ" //ViewControllerのタイトル設定
  table.dataSource = self
  table.delegate = self

Alamofire.requestメソッドの処理で、JSONデータの取得・パースが完了したタイミングでtableデータを読み込みます。

self.entryDataArray = feed["entries"] as! NSArray
self.table.reloadData() //取得したデータをテーブルビューに表示

さらに、UITableViewDataSourceプロトコルを追加した場合に必要なメソッドを追加します。

まずは、セルの数を返すメソッドです。
セルの数は配列entryDataArrayの要素数です。

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  return entryDataArray.count
}

次に、実際にデータを表示する処理です。
indexPathを使ってentryDataArrayからデータを取得し、CustomCellのLabelにセットします。
サムネイル画像の表示はちょっと面倒くさくて、wordpressの標準のRSSをJSONに変換した場合、画像のURLは結構深い階層に入っています。
それを力技で抜き出して、キャッシュを使って表示させます。
この辺り、もう少しスマートな書き方がありそうな気がしていますが、今の僕にはこれが限界っす…。

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
  let cell: CustomCell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! CustomCell //storyboardで作成した"Cell"を取得

  var entryDic = entryDataArray[indexPath.row] as! NSDictionary //配列の"indexPath.row"番目の要を取得

  // 取得した要素からタイトル、掲載日、カテゴリー(複数選択している場合は最初のカテゴリー)をCellにセット
  cell.title.text = entryDic["title"] as? String
  cell.date.text = entryDic["publishedDate"] as? String
  let category = entryDic["categories"] as! NSArray
  cell.category.text = category[0] as? String

  // JSONデータの中から、thumbnail画像のURLを取得し、NSURL型に変換(この辺り、力技すぎるのでもう少しかっこいい処理がしたいところですが…。)
  var mediaGroups:NSArray = (entryDic["mediaGroups"] as? NSArray)!
  var mediacontents:NSDictionary = (mediaGroups[0] as? NSDictionary)!
  mediaGroups = (mediacontents["contents"] as? NSArray)!
  mediacontents = (mediaGroups[0] as? NSDictionary)!
  let urlString = mediacontents["url"] as! String
  let imgURL: NSURL? = NSURL(string: urlString)

  // キャッシュがあればキャッシュを表示、なければ非同期通信で画像データを取得して表示
  if let img = imageCache[urlString] {
    cell.thumbnail?.image = img
  }
  else{
    let request: NSURLRequest = NSURLRequest(URL: imgURL!)
    let mainQueue = NSOperationQueue.mainQueue()
    NSURLConnection.sendAsynchronousRequest(request, queue: mainQueue, completionHandler: { (response, data, error) -> Void in
      if error == nil {
        let image = UIImage(data: data)
        self.imageCache[urlString] = image
        dispatch_async(dispatch_get_main_queue(), {
          cell.thumbnail?.image = image
        })
      }
      else {
        println("Error: \(error.localizedDescription)")
      }
    })
  }
  return cell
}

これでエラーが消えたはずなので実行!
無事に表示されました。
テキストラベルの位置やサイズが思い通りに表示されない場合は、トライアル&エラーで数値を調整してください。
IMG 7772

最後に微調整です。
セル間の境界線に微妙な隙間ができているので、それを消すためにcell.layoutMarginsを設定。
また、右端に「>」記号を表示させるために、accessoryTypeを設定します。

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
  let cell: CustomCell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! CustomCell
cell.layoutMargins = UIEdgeInsetsZero
cell.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator

再び実行。
IMG 7771
いい感じに出来ました!


というわけで今回はここまで。
次回は、リストをタップした時の処理を実装したいと思います!
(今回も「AppleWatch」関係の処理は出てきませんでした…。もう少しお待ち下さい!)

連載記事

第1回「HTTP通信でブログのデータを取得する」
第2回「テーブルビューに情報を表示する」
第3回「WebViewでページを表示する」
第4回「お気に入りの記事を保存する(前編)」
第5回「お気に入りの記事を保存する(後編)」
第6回「AppleWatch対応」

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です