UITableViewのスクロールで落ちる

2011/01/27

また君か!と、操作が難しいUITabeViewの再描画処理。

でも今回はうっかりと、かなり初歩的な事を知らないばかりにハマりました。 おかしい!?retainもしているはずなのに・・・。

結論から言うと、取得データの更新が保証されないままUITableViewを再描画をしていました。

IBのバインディングは確実にしよう!

まず、UITableView:reloadData をするもスクロールすると「NSMutableArrayの数があわないよ!」みたいな英語のエラーで落ちる。

データが更新されてるいるからと、まさかUITableViewのバインディングがされていないとは気づかなかった・・・。

(1) データを違う結果で取得。 (2) NSMutableArrayにデータが受け渡される。 (3) UITableViewがバインドされていないために、numberOfSectionsInTableView、numberOfRowsInSectionが呼ばれない。 (4) スクロールするとデータ取得したNSMutableArrayで描画が始まる。 (5) スクロール途中でデータ数があわないため落ちる。

UITableView は@synthesizeされているからバインディングされてなくても動作上動いてしまうんですよね。

nilチェックの落とし穴

nilとNULLは違う

これはよく言われる事ですが、まさにこれでした。 データ取得処理でnilでなく、NULLでデータが返えっていたのでcountできていなかったみたいです。

で、[NSNull null] の存在を初めて知りました・・・。

- (void)loadData {
    NSMutableArray *results = [[api publicArtistList:indexName :@""] retain];
    if (results != nil) {
        keys = [[results valueForKey:@"keys"] retain];
        artists = [[results valueForKey:@"artists"] retain];
        [artistListTable reloadData];
    }
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    if (artistKeys == (NSMutableArray *) [NSNull null]) {
        NSLog(@"NULL");
        return 0;
    } else {
        NSLog(@"OK");
        return [keys count];
    }
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if (artistKeys == (NSMutableArray *) [NSNull null]) {
        NSLog(@"keys NULL");
        return 0;
    } else if (artists == (NSMutableArray *) [NSNull null]) {
        NSLog(@"artists NULL");
        return 0;
    } else {
        NSLog(@"OK");
        return [[artists valueForKey:[artistKeys objectAtIndex:section]] count];
    }
}