SSブログ

UITableViewのセルが2倍に増える謎 [楽しいプログラミング]

さて、ここからが本題である。(何のだ?)

iOSアプリ制作において、またまたおかしな現象が起きた。今度はXcodeとかの設定の問題ではなく、純粋にプログラミングの問題である。何が原因かはわかったが、何が悪いのかはさっぱりわからない。まあ先日の「?」のように、カタギのプログラマであればまずやらないようなことなんだが、一応記録しておく。

例えばこういうテーブル、

table1.png

これが、或〜る日突然、こうなっていたのだ。

table2.png

以前、テレビの天気予報の表示で、気温が「99.9度」になっているのを観たことがある。うんうん、気持ちは良くわかるぞ。まさにそれだ。何でデフォが表示されている?
「或る日突然」というのはおそらくXcodeを8.0にアップデートした後である。その後こちらも小規模なバグを修正して更新の審査申請している。問題が起きているのはその更新バージョンである(よく審査通ったな(笑))

Storyboard上のプロトタイプセルは以下の通り。

tableS.png cell.png

reuseのIDとして上のセルに”switchCell”、下のセルにはただの"cell"と命名した。下のは他にも使いまわすスタンダードなものだから単純な名前で良いだろうと。これが後で死を招く。

さて、実装である。以下は正しい例、品行方正かどうかはわからないが、とりあえず修正後正しく動いたものである。


- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 2;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

UITableViewCell *cell = nil;
switch (indexPath.row) {
case 0:
{
cell = [tableView dequeueReusableCellWithIdentifier:@"switchCell" forIndexPath:indexPath];
UILabel * label = [cell viewWithTag:1];
label.text = @"あなたはぷにぷにですか?";
break;
}
case 1:
cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
cell.textLabel.text = @"ぷにぷにのタイプは?";
cell.detailTextLabel.text = @"ものすごいぷに";
break;
}
return cell;
}

非の打ち所のない、ベタベタなテーブルの実装である。

さて、UITableViewControllerクラスはご存知のように、ファイルを新規で開くとデフォルトで何やらごちゃごちゃ書いてある。
上記該当部分に関してであれば例えばこんな感じ。

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
#warning Incomplete implementation, return the number of sections
return 0;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
#warning Incomplete implementation, return the number of rows
return 0;
}

/*
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:<#@"reuseIdentifier"#> forIndexPath:indexPath];

// Configure the cell...

return cell;
}
*/

最後のtableView:cellForRowAtIndexPath:にはコメント内にご丁寧にセルの取ってき方が書いてある。
私は当初、ここにデフォルトのセル(この場合"cell")を設定し、後で上書きすれば良いだろうと考えた。つまりはこんな感じである。



- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 2;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
switch (indexPath.row) {
case 0:
{
cell = [tableView dequeueReusableCellWithIdentifier:@"switchCell" forIndexPath:indexPath];
UILabel * label = [cell viewWithTag:1];
label.text = @"あなたはぷにぷにですか?";
break;
}
case 1:
cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
cell.textLabel.text = @"ぷにぷにのタイプは?";
cell.detailTextLabel.text = @"ものすごいぷに";
break;
}
return cell;
}

強参照で上書きならば何の問題もないと思ったのだが、これ、何かまずいのだろうか?何かやらかしているのだろうか?Xcode7の段階ではこれで問題なかった。申請前に何度もテストしたので間違いない。
ところが今現在これでビルドかけると、上で示したデフォルト「Title」祭りになる。

「self.tableView recursiveDescription」してみると、テーブル内の同じframeになぜかセルが2つづつ存在している。「Title」祭りと、ちゃんとtableView:cellForRowAtIndexPath:内でぷにぷにを設定したものとである。
これは謎だ。こちらのあずかり知らぬところでtableView:cellForRowAtIndexPath:がもう一回走っているのではないかと、ログやブレークポイント入れてみたが、その気配はない。

まあ何にせよ、tableView:cellForRowAtIndexPath:でリターンするUITableViewCellに関しては初期化しておくのが無難なようである。初期化しない、宣言しっぱなしというのも多分リスキーだろう。


コメント(0)  トラックバック(0) 
共通テーマ:blog

コメント 0

コメントを書く

お名前:[必須]
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。