Objective-CでのUITableViewの作り方

iPhoneといえばTableViewですよね。


そして、TableViewを作ることすら出来なくてObjective-CによるiPhoneアプリ開発を挫折してTitaniumやることにしたという話を時々聞くので作り方の紹介です。
(まぁシンプルなTableViewベースのアプリケーションであればTitaniumでやった方が簡単に作れていいかなぁとは思います)

  • まずはわかりやすいようにViewBaseで作ります。
    • ほとんどの場合はNavigationBaseで作ることになると思うのですが、今回はシンプルな構造でわかりやすくするためにViewBaseで

f:id:koba04:20120304003815p:plain

  • とりあえずTableViewを貼り付けます。

f:id:koba04:20120304004312p:plain

  • TableViewを接続します

f:id:koba04:20120304004729p:plain

  • DataSourceとDelegateを設定します。
    • DataSourceはデータに対する要求を処理してくれるクラスで、DelegateはTableViewに対してのイベントを処理してくれるクラスを指定するもので、ここでは同じViewControllerにしています。

f:id:koba04:20120304004829p:plain

  • ここまでくれば後は少しコード書くだけです。
  • まずは.hにデータとして使う配列やdelegateを指定します。
@interface TableViewSampleViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>{
    
    UITableView *sampleTable;
    NSArray *tableData;
}
  • .mにデータとして使う配列にデータを入れます。
- (void)dealloc
{
    [sampleTable release];
    [tableData release];
    [super dealloc];
}
:
- (void)viewDidLoad
{
    [super viewDidLoad];
    tableData = [[NSArray alloc]initWithObjects:@"新宿", @"代々木", @"原宿", @"渋谷", nil];
    
}
  • UITableViewDataSourceのdelegateでrequiredになっているメソッドを実装します。
// 指定したindexのcellを作成する。
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    // セルを再利用するためのコード
    static NSString *cellID = @"SampleView";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc]initWithFrame:CGRectZero reuseIdentifier:cellID]autorelease];
    }

    // ただ配列の値を設定しているだけ
    cell.textLabel.text = [tableData objectAtIndex:indexPath.row];
    return cell;
}


// データの総件数を返すメソッド
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [tableData count];
}
  • とりあえずこれだけ指定すればこんな感じでTableViewを使うことが出来ます。

f:id:koba04:20120304012419p:plain

  • あとはcellをクリックしたのイベントを追加したければ下記のメソッドを実装すれば出来ます。
(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath


簡単ですね!


ソースはgistにあげておきました。
https://gist.github.com/1966940

XCodeの使い方。

普段はVimを使っていて、Objective-C書くときだけXCode使っているので操作に慣れず非効率になっているので、
使い方ぐぐってもすぐ忘れるので自分の用にメモするページを作ることにする。

VPSにつくろうかと思ったけど、githubのwikiでいいんじゃない?と思ったので、githubで書いていくことに。

https://github.com/koba04/xcode-operation



markdown記法にもテーブルはないのか??

iPhoneアプリ開発の勉強(11日目)


やったとこ。Chpter5、6のLESSON18〜20


小さく注意書きにも書かれている通りなのか、家の回線につないだマシンだとlocationManager:didUpdateToLocation:fromLocationメソッドが呼ばれず現在位置の取得が出来なかった。なのでここの動作検証は出来ていない。

  • 位置情報を使うときはMapKitとCoreLocationのframeworkをFrameworksのディレクトリに入れてやる。
  • 位置情報の取得はCLLocationManagerクラスを使って、delegateで取得する。
  • MKReverseGeoCoderは取得に失敗することが多いらしい。
  • Xcodeで複数のソースに切り替えはCtrl+1、Ctrl+2、Ctrl+3とかでやる方法以外に何かないのだろうか。。
  • self.view.frameは親ビューを基準とした位置になってself.view.boundsは自分自身が基準(?)になっているので常に(0,0)が基準点になる。

iPhoneアプリ開発の勉強(10日目)+おまけ

やったとこ。Chapter05のLESSON17。

ここはただMapを表示させるだけ。
憶えておく点としては、Build PhaseからMapKitとCoreLocationフレームをワークを追加しておくことくらい。




やったとこ。「05-03分数電卓の例」から「07-03ドット演算子によるプロパティへのアクセス」まで。


メモリ管理方法

  • ここでは第3版から追加された新しいメモリ管理方法のARCについての説明など、メモリ管理についてや、アクセサメソッドの定義方法について書かれている。
  • ARC方式では@autoreleasepoolのブロックを定義するとことでretainやreleaseやautoreleaseなどをプログラマが意識しなくてすむ。
    • 逆に使ってはいけない。
@autoreleasepool {
    :
    :
}
  • ブロックを抜ければ自動的に開放されて楽そうだけど、循環参照は__weakで弱参照にする必要があったり、alloc、copy、mutableCopy、new、initのメソッドファミリに一致するメソッド名を通常のメソッドで使っていけないという注意点がある。
  • deallocでのreleaseも必要ない。
  • まぁそれより何より、今開発環境がSnow Leopardなので使えない。。でもこれからも開発はARC方式を使ったメモリ管理方法が推奨されている。
  • この辺りの参照がとかはCのポインタの知識も必要だったり、後から定期的に見直す章になりそう。
  • ガーベジコレクションの項目はあまりちゃんと読んでいない。iOSでは使えないので。
  • 手動のメモリ管理方法からARC方式を使うコードへの変更はXCodeのメニューから出来るらしい(未確認)


プロパティ

  • インターフェイスファイルで@propertyで宣言して、実装ファイルで@synthesizeで宣言する。実装を書く場合は@dynamicで宣言する。参照カウンタ増やす場合はretainでオブジェクト以外やカウンタを増やさない場合は、assignで。ARC方式でも指定する必要がある。
  • ドット演算子が使えるのはクラスで型宣言している場合だけ(idはダメ)
    • 引数を持たないメソッドはドット演算子で呼べるけど、使うのはプロパティで宣言されているものだけにするべき。
  • プロパティはコーディングを楽にしてくれる素晴らしい仕組みだと思った。


とても大切なことが書かれているところでゆっくり読んだつもりだけど、まだしっかりとは理解できていないかも。ARCでやるにしても参照カウンタに仕組みは知っておく必要があるなぁと思った。




おまけ

  • プログラマの数学を息抜きに読んでいるけど、これはとてもいい本。高一で数学から逃げた自分にとってはとてもありがたくて、ドモルガンの法則とかカルノー図とかがとてもわかりやすく説明されていて、カルノー図を使ってグループ化して論理式を単純化する仕組みの説明などおおぉーと思って楽しく読めた。
  • まだ真偽値のところを読んだだけなので、続きも楽しみ。

iPhoneアプリ開発の勉強(9日目)

やったとこ。Chapter4のLESSON15、LESSON16。

ここでは写真の表示とセピアに加工して保存することをやった。
写真をセピアにするところのコードは少しややこしいけど、それ以外のところはとてもシンプルで分かりやすかった。
セピアにするところはこの本の性質からしてすると?と思ったけど、まぁわかりやすい変化を見せるために入れたのかなとも思った。

  • UIImageWriteToSavedPhotosAlbum関数が同期的に写真を保存してくれずにselector指定して完了時の処理を書くようになっているのは、ブロッキングしてユーザーに待たせないための工夫になっていてなるほどなぁと思った。




やったとこ。「04-05クラスオブジェクト」から「05-02手動カウンタ管理方式」まで。


クラスメソッド

  • クラスメソッドの定義は頭に(+)。
  • NSObjectにあるclassメソッドでクラスオブジェクトを取得することが出来る。(型はClass)
    • クラス名はハードコーディングしたくない状況の時は下みたいな感じでクラスメソッドを呼び出すことが可能。
[[obj class] classMethod] 
  • クラス変数はないのでstaticをつけた変数で定義する。その場合継承はされないのでサブクラスで使いたい場合は、アクセサを用意する。
  • クラスオブジェクトの初期化はinitializeメソッドで呼び出される。勝手に呼び出されるので明示的に書いちゃダメ。また、複数回呼ばれてもおかしくならないようにコードを書いておく必要がある。(初期化フラグを用意するとか)
  • initializeはid型で返すべし。


メモリ管理

  • Lion、iOS5以降では新しく追加されたARCという方式を使用することが推奨されている。その場合でもリファンレンスカウンタ方式の仕組みは知っておいたほうがいい。
  • allocで確保して、retailで参照カウンタをインクリメント、releaseでデクリメント。
  • そのオブジェクトが持っている変数の開放は、deallocで行う。
  • NSAutoreleasePoolに任せる方法もある。
  • コンビニエンスコンストラクタはautoreleaseした状態で作成される。


この辺りのロジック以外の部分に気を使う必要があるというのは、やっぱり面倒なところではあるなと思った。