アプリ開発『WeightControl』vol.24 タブバーアプリケーションでCore-Plotによる折れ線グラフを描画する方法
グラフ描画について引き続き頭を悩ませていますが、前回PNChartというライブラリを使うことにしました!! と、宣言しておきながら、最終的にはCore-Plotというライブラリで描画することになりました。
なぜかというと、PNChartのカスタマイズが難しいことがわかったからです。(難しいというよりは、ネット上にPNChartに関する記事が海外含めてほとんど無い)
そこで、今回はCore-Plotでのグラフ描画を下記サイトを参考にしながらやってみました。とてもわかりやすく、結構カスタマイズしやすいです。
iPhoneアプリ開発でよく使われているグラフ描画ライブラリ『CorePlot』でiPhoneアプリで折れ線グラフを描く - プログラミング技術メモとちょっことアプリ開発メモ
ただし、僕は今回タブバーアプリケーションを作っているのですが、上記サイトではviewDidLoad内にコードを書いているため、タブバーではグラフに載るべきデータを修正してもアプリ起動時しかグラフが描画されないので、viewDidAppear内に書く必要がありました。
しかし、それだけだとタブを他のタブに切り替えてからまた戻ってくると、最初に描画されたグラフと同時に、新たに描画されるグラフも重なって表示されてしまいます。viewDidAppearなので、タブを開く度に一本ずつ表示されるグラフが増えてく感じになってしまうからです。また、Y軸やX軸のラベルも更新前のものの上に更新後のものが重なって表示されてしまいます。
これを避けるためには、ホスティングビューとグラフの生成、追加をviewDidLoad内で行うことで、グラフの生成がアプリ起動時の一回だけになることから、タブを切り替えた時にラベルが重ならないようにすることができます。下記サイトを参考にしました。
ios - Core Plot 1.0 how to implement reloadData method? - Stack Overflow
つまり、viewDidLoadのコードは下記のようになります。
---------------------------------
- (void)viewDidLoad
{
[superviewDidLoad];
// ホスティングビューを生成、画面に追加
CPTGraphHostingView *hostingView = [[CPTGraphHostingViewalloc] initWithFrame:CGRectMake(0, 0, 320, 400)];
[self.view addSubview:hostingView];
// グラフを生成、ホスティングビューに追加
graph = [[CPTXYGraph alloc] initWithFrame:hostingView.bounds];
hostingView.hostedGraph = graph;
}
---------------------------------
さらに、viewDidAppear内にはグラフに関するデータがごっそり残っているのですが、タブを開く(開き直す)度に最新のデータが反映するように更新しなくてはならないので、ここのサイトの情報を見てviewWillDisappearメソッドを追加しました。
- (void)viewWillDisappear:(BOOL)animated
{
[superviewWillDisappear:animated];
hostingView.hostedGraph = nil;
[scatterPlotData removeAllObjects];
}
本来はreloadDataメソッドを使って更新するらしいのですが、ちょっといろいろ試してみても更新成功することができなかったので、この方法を採用しました。
タブバーアプリケーションでCore-Plotによるグラフ描画を行う場合、viewDidLoad とviewDidAppearに分けてコードを書かなくてはならないということがミソなんですね。
例えば、僕はここのサイトを参考にしましたが、そこのviewDidLoad内に書かれているコードのうち、以下の部分のみは切り取って、viewDidLoad内に貼り付ける必要がありました。
---------------------------------
// ホスティングビューを生成
CPTGraphHostingView *hostingView =
[[CPTGraphHostingView alloc] initWithFrame:CGRectMake(0, 0, 320, 320)];
// 画面にホスティングビューを追加
[self.view addSubview:hostingView];
// グラフを生成
graph = [[CPTXYGraph alloc] initWithFrame:hostingView.bounds];
hostingView.hostedGraph = graph;
---------------------------------
これで、タブバーアプリケーションでもCore-Plotでグラフ描画が正しくできるようになりました!
Y軸は体重になっていますが、次回からはX軸を日付にしたいと思います。(体重値はランダム生成しています 笑)今は日付にすることを想定して、30日分のメモリを入れている状態です。
アプリ開発『WeightControl』vol.23
グラフのラベルやデータを編集したり、位置を調整したりということでしたが、今回はグラフのY軸ラベルの調整にかかりました。
そこで、ダウンロードしたライブラリとにらめっこした結果、PNLineChart.mの中にある下記項目を調整すればY軸ラベルの値を調整できることがわかりました!
・『float level』の値
・ label.textの『level * index』
『float level』の値はY軸ラベルの初期値0の次に来る値を何にするかっていうのを指していて、『level * index』の部分はY軸ラベルの値をどういうペース(『float level』を何倍していくか)で増やしていくかっていうことを指しています。
もちろん、コードを書き換えれば初期値を0以外にすることもできるし、何倍とかのペースじゃなくて1ずつ足していくみたいなふうにすることもできます。
今回は初期値を設定タブに登録した(目標体重-1)にして、1ずつ足していくような感じにしました!今回は目標体重75kgにした例です。
ただ、Y軸のラベルは予定通りに変更することができましたが、あくまでラベルはラベルなわけで、中身のチャートそのものもラベルに合わせて変更してくれるわけではなかったです。なので、次回はチャートもラベルに合わせて変化するようにしてみたいと思います!
アプリ開発『WeightControl』vol.22
とりあえず前回までにs7graphviewのライブラリでグラフを描画してみましたが、サンプルコードを書き換えて自分の好きなようにカスタマイズするのが難しいことが判明。しかも、X軸のラベルがズレているのも解決できず。。。そのため、他にグラフ描画に良い方法がないかを再度リサーチしました。
リサーチの結果、「PNChart」が良さそうかなということを発見しました!
→オープンソースライブラリ:PNChart シンプルで美しいiOS用グラフライブラリ | iOS開発者@日本
ここで、導入方法の①でめちゃめちゃつまづきまくりました。cocoapodsとか書いてるし、rubyを使うとか書いてるし、今までの経験上全然やったことのないものが出てきていますが…仕方がないから下記サイト等を参考にしたけど、全然うまくいかない。。。
→MavericksでCommand Line Tools for Xcodeをインストールする - Qiita [キータ]
→MavericksでCommand Line Developer Toolsをインストールする方法が変更 | Act as Professional - hiroki.jp
と思ったら、気付きました。導入方法は①か②の好きな方法を選択してねということだったのね!!要は、githubの「Download ZIP」からPNChartをダウンロードして、それをプロジェクトに追加してねと。。。そして、QuartzCore.frameworkのフレームワークをXcodeのプロジェクトに追加して、あとは実装するためのコードを書いてねと。。。なーんだ、そういうことか!!っていうのに気づくのに何時間も費やしました。。。
で、"PCChartViewController.m"と"PCChartViewController.h"を参考にしつつ、実装コードを書いてビルドっと…すると、なんと、エラー!!というか、エラーは無いけどシミュレーターは真っ白!!
これは、スクロールビューではなく、ただのビューに乗っけるとOKでした。
[self. chartScrollView addSubview:lineChartLabel];
[self. chartScrollView addSubview:lineChart];
↓
[self.view addSubview:lineChartLabel];
[self.view addSubview:lineChart];
そうすると、ここのお手本と全く同じグラフが表示されました!!
なので、今回のアプリではこのライブラリを使ってグラフを表示させていきます。
次回からは、このグラフのラベルやデータを編集したり、位置を調整したりしていこうと思います!今はiAdと重なってたり、そもそも今回棒グラフは使わないので削除して、折れ線グラフをブラッシュアップしていきます。
アプリ開発『WeightControl』vol.21
s7graphviewのライブラリでグラフを作成したいと思います。ただ、ググっていると、オリジナルのファイルがある場所は既に404エラーとなっているし、あまり最近のs7graphviewを使ったという記事が見つからないため、もしかしたらこの手法って既に古いのかな??とか思ってしまったり。。。
とはいっても、現時点ではあまりグラフを描画するための選択肢を持っていないので、ゴリゴリと今ある情報でコーディングしていきたいと思います。手順は前回の記事の通り、この記事を参考にして進めていきます。
その中で、結局ここのサイトから s7graphviewのライブラリをダウンロードすることになるのですが、どこからダウンロードすればいいのか最初全然わからなかったwww
で、結局気づいたのは、右カラムの「Download ZIP」からダウンロードできました。これがかなり気づきにくい。。。
とりあえず、ダウンロードできたら上記のこの記事の手順通りにやってみるのですが、まずはエラー等はなくビルドできる感じです。ただ、実際にビルドしてみると、いきなり下記のエラーが大量に表示されます。
【S7GraphView.m】
エラー①: 'release' is unavailable: not available in automatic reference counting mode
→こちらの記事に解消方法あり。deallocメソッド削除。
エラー②: ARC forbids explicit message send of 'release'
→こちらの記事に解消方法あり。[[UIColor blackColor] retain];ではなく、retainを削除して、[UIColor blackColor];だけにすることで解消。
エラー③:'retain' is unavailable: not available in automatic reference counting mode
→上記②と同様の対処で解消。
エラー④: Too many errors emitted, stopping now
→上記①〜③を解消することで消えました。具体的なエラーを指していたわけではなくて、単に、Xcode君に「おまぃ、エラー多すぎやんwww」っていうのを言われただけみたいです。
ただし、上記①-④を解消したところ、新たにこんなエラーが出現しました。
エラー⑤: Property implementation must have its declaration in interface 'SecondViewController'
エラー⑥: Property 'graphView' not found on object of type 'SecondViewController *'; did you mean to access instance variable 'graphView'?
→上記⑤、⑥はヘッダファイルで宣言しているgraphViewですが、何となくエラーの内容見て、既に宣言済みであることから、「self.graphView」を「graphView」だけにしたらエラーが解消されました。
【S7GraphView.h】
エラー: Existing instance variable '_dataSource' for property 'dataSource' with assign attribute must be __unsafe_unretained
→こちらの記事に従って、@interface S7GraphView : UIView の{}内に宣言しているものを削除した結果エラー解消しました!
さらに、下記のような警告が表示されていました。
【S7GraphView.m】
警告①: 'UILineBreakModeTailTruncation' is deprecated: first deprecated in iOS 6.0
警告②: 'UITextAlignmentRight' is deprecated: first deprecated in iOS 6.0
警告③: Implicit conversion from enumeration type 'enum UILineBreakMode' to different enumeration type 'NSLineBreakMode' (aka 'enum NSLineBreakMode')
警告④: Implicit conversion from enumeration type 'enum UITextAlignment' to different enumeration type 'NSTextAlignment' (aka 'enum NSTextAlignment')
→こちらの記事の【UILabel】を参考に変更したところ、警告解消。
警告⑤: 'drawInRect:withFont:lineBreakMode:alignment:' is deprecated: first deprecated in iOS 7.0 - Use -drawInRect:withAttributes:
→iOS7から仕様が変わったようですが、解決策不明のためシカトしました。
で、エラー無し、警告3のままでビルドしたところ、グラフが出ました!!
が、、、X軸のラベルの位置がズレている。。。なぜだー!!!
このあたりは、次回に持越したいと思います。。。
ちなみに、グラフを表示させたいクラスの実装ファイルやDelegate.m,
.hのコードはこちらからサンプルをダウンロードして、確認しながら調節しています。
アプリ開発『WeightControl』vol.20
今回から体重グラフを描画していきたいと思うのですが、過去の独学経験の中でグラフ描画は一切したことないので、未知の機能を実装しようとしていますwww
そこで調べたところ、どうやらiPhoneでグラフを描画しようとした場合、この2つのライブラリがメジャーなようです。
・s7graphview
・core-plot
今回はs7graphviewの方を使ってやってみたいと思います。なぜこっちを使うことにしたかというと、何となくですw
ググってたら、折れ線グラフの描画はこっちの方が評判良さそうと感じたので。
このあたりのサイトを参考にしながら実装していこうと思います!
・iPhone用グラフ描画ライブラリ s7graphview の使い方 - Over&Out その後
・UIView to draw sweet graphs « Mac-ISV
ちゃんとグラフが描画できるでしょうか。。。不安ですが、多分、何とかなるでしょー!!