この記事には広告を含む場合があります。
記事内で紹介する商品を購入することで、当サイトに売り上げの一部が還元されることがあります。
WordPressを使っているサイトのネイティブアプリ化(AppleWatch対応版)のチュートリアル第2回目です。
(第1回はこちら→第1回「HTTP通信でブログのデータを取得する」)
作るのはこんなアプリ
アプリ版AppleWatchJournalをそのまま作成します。
詳しい動作は実際のアプリを参照ください!
※そして、もしよかったらAppleWatchJournalも定期的にチェックしていただけますと超幸いです。よろしくです。
ナビゲーションバーを作る
Navigation Controllerを設置する
「Main.storyboard」を選択。
View Controller SceneのView Controller(黄色い四角のアイコン)を選択した状態で、メニューのEditor > Embed In > Navigation Controllerを選択。
キャンバス上にNavigation Controllerが追加されます。
Navigation Controllerにタイトルを設定
ナビゲーションに表示するタイトルを設定します。
ViewController.swiftのviewDidLoadメソッドでtitleプロパティを使って設定します。
override func viewDidLoad() { super.viewDidLoad() self.title = "AWJ" //ViewControllerのタイトル設定
Navigation Controllerの色を設定
Navigation ControllerのNavigation Barを選択。
Attributes Inspectorの「Bar Tint」で好きな色を選択します。
ただし、選択した色によっては、タイトルやステータスバーの色が「黒」なのが読み難い場合があります。
そういう場合はタイトルの色も変更した方がいいでしょう。
ステータスバーの色は基本的に「黒」か「白」しか選べないので、タイトルもそれに合わせて「黒」か「白」にしておくと無難なデザインにまとまると思います。
タイトルの文字色を変更
ナビゲーションバーの背景色と同様に、Navigation ControllerのNavigation Barを選択→Attributes InspectorのText Colorを白に変更します。
ステータスバーの文字色を変更
Supporting Filesの「Info.plist」に以下のステータスを追加します。
・View controller-based status bar:NO
・Status bar style:UIStatusBarStyleLightContent
※「UIStatusBarStyleLightContent」は選択メニューに出てこないので、直接文字列として入力してください。
これで、ナビゲーションバーの色設定は完了です!
メインページを作成する
続いて、Main.storyboardでメインページを作成していきましょう。
Table Viewを配置する
Object LibraryからTable Viewを選択、View Controllerにドラッグ&ドロップ。
ドラッグすると中心線を表すグリッドが表示されるので、上下左右の中心位置にドロップしましょう。
Table Viewを選択した状態で、画面右下の「Resolve Auto Layout Issues」から「Add Missing Constraints」をクリック。
様々なサイズのiPhoneでいい感じに表示されるように、レイアウト設定に必要な数値を自動で入力してくれます。
(この辺りのUIの作り方は正直まだよくわかってないところもありまして…。こんな本を買ってお勉強中です↓)
Attributes InspectorでPrototype Cellsを「0」から「1」に変更。
Size InspectorでRow Heightを「100」に変更。
Table Viewを選択した状態で、Connections InspectorのOutletsエリアで、datasourceの横の○をView Controllerにドラッグ&ドロップして、接続します。
同様に、delegateもView Controllerに接続します。
最後に、Attribute InspectorのIdentifierに任意の名前をつけます。今回はわかりやすく「Cell」としました。
Table View Cellを作成する
Object LibraryからImage Viewを選択、Table View Cellにドラッグ&ドロップします。
画面左端に表示されるように、Size Inspectorで位置とサイズを変更。
ViewのModeを「Redraw」に変更。(サイズに対する画像のフィット方式を変更しています。)
同じように、「Label」を3つ、Tabele View Cellにドラッグ&ドロップします。
Size Inspectorを使って、いい感じに配置します。
(この辺りのUIの作り方は正直まだよくわかってないところも(ry…
このあたりは、あとで実際にデータを表示した状態で、実機で動かしながら微調整した方が良いかもしれません。
それぞれのLabelに対して、Attribute Inspectorでフォントサイズ・色・行数などを指定します。
上から
・「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…」
「Cocoa Class」を選択。
クラス名は適当に。Subclass ofは「UITableViewCell」を選択してください。
ファイルの保存場所を指定(デフォルトのままでOKです)して、「Create」をクリック。
Custom Cellクラスとstoryboardを接続
Main.storyboardに戻り、Table View Cellを選択した状態で、Identify InspectorのCustom Classで、先ほど作成した「CustomCellクラス」をClassに指定します。
さらに、TableViewCellを構成しているImage ViewとLabelを、CustomCellにOutlet接続します。
接続する際の「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接続します。
続いて、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 }
これでエラーが消えたはずなので実行!
無事に表示されました。
テキストラベルの位置やサイズが思い通りに表示されない場合は、トライアル&エラーで数値を調整してください。
最後に微調整です。
セル間の境界線に微妙な隙間ができているので、それを消すために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
再び実行。
いい感じに出来ました!
というわけで今回はここまで。
次回は、リストをタップした時の処理を実装したいと思います!
(今回も「AppleWatch」関係の処理は出てきませんでした…。もう少しお待ち下さい!)
連載記事
第1回「HTTP通信でブログのデータを取得する」
第2回「テーブルビューに情報を表示する」
第3回「WebViewでページを表示する」
第4回「お気に入りの記事を保存する(前編)」
第5回「お気に入りの記事を保存する(後編)」
第6回「AppleWatch対応」