必要環境
今回の記事における筆者の環境は下記の通りです。実際は、これより新しくても動作すると思われます。
- Xcode Version 7.2(7C68)
- Mac OS X Yosemite 10.10.5
- Xuni 2015J v3
まずは動かしてみよう
Xuniの概要やインストールについては、第1回で説明していますので省略します。早速サンプルプログラムを動かしてみましょう。
サンプルプログラムはAndroidと同様の場所に保存されています。
~/Documents/XuniJp/iOS/Samples
Androidでも試したFlexGridのサンプルを見ていきます。
Xcodeからプロジェクトを開く
iOS版は、従来からあるObjective-Cと比較的新しいSwiftの2種類の言語を選択できます。今回は新しいSwiftを使用します。次のサンプルプロジェクトをXcodeにて開きます。
~/Documents/XuniJp/iOS/Samples/Swift/FlexGrid101

アプリを実行する
Runボタンをクリックして実行します。

シミュレーターが立ち上がり、アプリが起動します。「列の定義」をタッチしましょう。

Android同様スワイプでスクロール、タップで選択が出来ます。ダブルタップで編集は「セル内容の編集」の画面で出来ます。

アプリの実装を見る
iOSのアプリの画面はStoryBoardで組み立てます。各画面の遷移は線をつなげて関連を表します。今回は最初のMenuから各画面に遷移するので、Menuからの各画面への線が張り巡らされています。
実装の詳細を見てみると、画面名ごとにControllerがあります。例えば先の「列の定義」であれば、「ColumnDefinitionController.swift」になります。どのような実装になっているか見てみましょう。
class ColumnDefinitionController: UIViewController {
var _flex = FlexGrid()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
_flex.autoGenerateColumns = false
//(1)
let c1 = FlexColumn()
c1.binding = "customerID"
c1.header = NSLocalizedString("ID", comment: "")
c1.width = 100
let c2 = FlexColumn()
c2.binding = "firstName"
c2.header = NSLocalizedString("First name", comment: "")
let c3 = FlexColumn()
c3.header = NSLocalizedString("Last name", comment: "")
c3.binding = "lastName"
let c4 = FlexColumn()
c4.binding = "orderTotal"
c4.header = NSLocalizedString("Total orders", comment: "")
c4.format = "N1"
_flex.columns.addObject(c1)
_flex.columns.addObject(c2)
_flex.columns.addObject(c3)
_flex.columns.addObject(c4)
//(2)
_flex.itemsSource = CustomerData.getCustomerData(100)
//(3)
_flex.isReadOnly = true
//(4)
self.starSizing(_flex)
//(5)
self.view.addSubview(_flex)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
_flex.frame = CGRectMake(0, 65, self.view.bounds.size.width, self.view.bounds.size.height - 65)
_flex.setNeedsDisplay()
}
func starSizing(g: FlexGrid){
for var i : UInt = 0; i < g.columns.count; i++ {
var c = FlexColumn()
c = g.columns.objectAtIndex(i) as! FlexColumn
c.widthType = FlexColumnWidth.Star
c.width = (i == 0) ? 3 : (i == 3) ? 3 : 4
}
}
}
- FlexGridの各カラムを設定する。
- itemSourceに対してFlexGridに表示するデータソースを設定する。
- 読み取り専用にする
- スターサイズ機能を使用して列のサイズを横スクロールしないように調整する
- ビューにFlexGridを追加する
XuniのAndroid版と見比べてどうでしょうか? JavaとSwiftの文法の細かい違いはありますが、FlexGrid自体の使用方法はそれほど変わらないと思います。
クラウドにデータを用意する
次にクラウドと通信してデータを取得する部分を作成します。利用するデータは「Azure Web Apps」に用意します。データの準備やクラウドへの配置、REST API作成の手順は、第2回「クラウド上のデータをグリッドやグラフで表示してみよう」で作成したAndroidアプリと同じなので、第2回を参照してください。
FlexGridからREST APIを呼び出す
データをREST APIから取得する方法も、Androidアプリ同様に、Azure Mobile AppsのSDKを利用します。「MicrosoftAzureMobile.framework」をプロジェクトに組み込みます。サンプルコードでは、「ColumnDefinitionController.swift」に組み込んでいます。以降説明する実装はすべて組み込み済みです。

次に、前述の「ColumnDefinitionController.swift」の(2)でサンプルデータを作成していた箇所を、次のように書き換えます。
//(2) itemsSourceにAzureから取得したJSONを格納するように変更する
let client = MSClient(applicationURLString:"https://62ad1595-0ee0-4-231-b9ee.azurewebsites.net")
client.invokeAPI("population", body: nil, HTTPMethod: "GET", parameters:nil, headers: nil) { (data, response, error) -> Void in
let newArray = data!["populations"] as? NSMutableArray
let populationArray = NSMutableArray()
for item in newArray! {
let dicItem = item as! NSDictionary
let population = PopulationData()
population.year = dicItem["year"] as! Int
population.under14 = dicItem["under14"] as! Int
population.between15to64 = dicItem["between15to64"] as! Int
population.over65 = dicItem["over65"] as! Int
population.sum = dicItem["sum"] as! Int
populationArray.addObject(population)
}
self._flex.itemsSource = populationArray }
"https://62ad1595-0ee0-4-231-b9ee.azurewebsites.net"は、Azure Web AppsのURLで、第2回で取得方法を説明しています。<62ad1595-0ee0-4-231-b9ee>の部分はユーザーごとに異なりますので、皆様の環境に合わせて書き換えて下さい。
FlexGridの機能を見る
つづいて、FlexGridの機能を解説します。
フィルタ
フィルタについては「フィルタ処理」をご確認ください。

さらに「フィルタ処理」を選択するとフィルタ画面が表示されます。

フィルタ画面にて「Noah」と入力し、「値と同じ」を選び「フィルタ処理」をタッチします。

すると、「Noah」と一致するセルのみが表示されます。

実装の詳細は「FilterController.swift」及び「FilterFormController.swift」を参照して下さい。
ソート
再び「列の定義」を見ていただき、カラムをタップするごとに昇順・降順でソートが可能です。Androidと同様にデフォルトで有効になっており特に実装は不要です。年次をタップして降順にした画面がこちらです。

グラフを表示する
次にグラフで表示してみましょう。
FlexChartを追加する
グラフを表示するために、「XuniChartCoreKit.framework」と「XuniFlexChartKit.framework」をプロジェクトに追加します。

グラフ画面を表示するボタンを追加する
Androidと考え方は同じです。「ColumnDefinitionController.swift」にグラフ表示のボタンを追加し、「PopulationGraphController」の画面を表示できるようにします。画面を表示する際に、人口のデータをパラメーターとして渡します。
override func viewDidLoad() {
// ... 中略 ...
//(6) グラフ表示ボタンを追加
_graphButton = UIButton(type: UIButtonType.System)
_graphButton.setTitle("グラフ表示", forState: UIControlState.Normal)
_graphButton.addTarget(self, action: "graphButtonClicked", forControlEvents: UIControlEvents.TouchUpInside)
self.view.addSubview(_graphButton)
// グラフ表示ボタンが押された時の処理
func graphButtonClicked(){
self.performSegueWithIdentifier("GraphFormSegue", sender: self)
}

グラフ表示画面を実装する
Androidのときと少し違うのは、前の画面から受け取るパラメーターをセットするのは前の画面ということです。具体的には、ColumnDefinitionControllerのprepareForSegueにて、PopulationGraphControllerにitemsSourceをセットします。
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?{
if segue.identifier == "GraphFormSegue" {
let populationGraphController = segue.destinationViewController a PopulationGraphController
populationGraphController._chart.itemsSource self._flex.itemsSource
}
}
棒グラフが表示されます。

Androidと同様に、このままでは見づらいので折れ線グラフにしてみましょう。グラフの種類はPopulationGraphControllerに次のようにセットするだけで簡単に切り替えられます。
_chart.chartType = XuniChartType.Line

積み上げ面グラフにしてみます。設定は次の通りです。
_chart.chartType = XuniChartType.Area _chart.stacking = XuniStacking.Stacked

軸に説明を追加する
縦軸・横軸の単位を設定します。
_chart.axisX.title = "年次" _chart.axisY.title = "人口(単位:1000人)"

横画面も綺麗に表示されます。以下はiPadで表示させてみたものです。

ズームを有効にする
ピンチイン・ピンチアウトによるズームを有効にする場合、これもAndroidとほぼ同じコードで実現できます。
_chart.zoomMode = XuniZoomMode.XY
iPadでズームした場合、以下のような表示になります。

まとめ
Xuniで、iOSもAndroid同様にデータを表示することができました。iOS版も「Xuni for iOS のユーザーガイド」及び「Xuni for iOS のAPI リファレンス」が参考になりますが、Objective-Cで記述されているため、Swiftは多少読み替えが必要です。
そのときは本記事を参照していただくか、サンプルソースにはObjective-CとSwift版が同梱されていますので、両者を見比べるとヒントが得られるかもしれません。
Xuniは、AndroidとiOSで実装方法はほぼ同じで、画面もほぼ同様に表示されます。グリッドとグラフがひとつで実現でき、使い勝手も良いコンポーネントですので、ぜひ皆様お試し下さい。

