kaeruspoon

【iPhone】スレッド中で[UITableView reloadData]を使ってはいけない

iPhoneアプリでスレッドを使うとき、スレッド中でUITableView reloadDataを実行するとおかしなことになります。これはスレッドセーフではないからです。
UITableViewCellで画像を外部から持ってくるときは非同期なりスレッドなりを使うと思いますが、画像取得後にUITableView reloadDataで更新しようとしてこの現象に出会いました。

リンゴの水やり:performSelectorOnMainThread:... - livedoor Blog(ブログ)

この記事にあるように、スレッド中でperformSelectorOnMainThread:withObject:waitUntilDone:modes:メソッドを使用してメインスレッド上で実行するようにしてあげれば解決できます。

ImageCache.m - 画像取得用ライブラリ

- (void) imageCache:(NSString*)url { // NSThreadでデタッチされるメソッド
    NSAutoreleasePool* pool;
    pool = [[NSAutoreleasePool alloc]init];

    NSData *data = .... // 画像データの取得処理

    if ([delegate respondsToSelector:@selector(imageCacheFinished)]) {
        [delegate performSelectorOnMainThread:@selector(imageCacheFinished) withObject:nil waitUntilDone:YES];
    }

    [pool release];
    [NSThread exit];
}


TableViewDelegate.m - TableViewのデリゲート

- (void) imageCacheFinished {
    [self.tableView reloadData];
}


こんな感じ。

今週のおやすみでやったこと

240
ふぉとすにもあげたけど、ユルさんと一緒に下北沢のマジスパにひさしぶりにいってきました。辛さは「涅槃」でチキンを頼んだけど、やっぱりおいしいね。あとはガンダム00をみたり町田にお出かけしたりkaeruspoonにmemcachedを適用してみたりグランツーリスモをやったりニコニコ動画をみたりしてました。

時間割をはじめる

ぼくは長いブランクもあるせいか、同年代のエンジニアにくらべて圧倒的に知識量が少ない。はっきりと身についているものがあまりないのだ。なんとなく知っている、昔やったことがある程度のレベルのものが多くて、同じことをまたググってるよおれ、と思うことも多い。勉強も、自分が興味をひかれたものをふらふらとやっているので中途半端だ。
なので、ちょっときちんと勉強してみることにした。ぼくは意思が弱くてすぐにさぼりがちなので、時間割をつくってそれにしたがうようにする。勉強しても知識が定着しないのでちゃんと復習もするようにしよう。

パフォーマンスチューニングをする

 ユルさんが仕事にいってヒマなので、kaeruspoonのパフォーマンスチューニングをしました。YSlowで計測できる、フロント側の対策です。以前やっていたのですが、OSをcentOSに替えたあとはメンドくさくてapacheの設定をいじってなかったのでした。deflateとexpiresの設定をしただけだけど。
あと、google-code-prettifyのJSでなぜかエラーが出ていたのだけど、addEventListenerで関数を呼んでいたところをbodyタグのonloadで呼ぶようにしただけで出なくなりました。よくわかんないな。

Railsのクラス定数にからむ罠にハマる

今日の失敗。
こんなmodelがあって

class Article < ActiveRecord::Base
  TITLE = "xxのブログ"

  def self.title
    TITLE
  end
.....
end

こんなhelperがあったとき

module ArticleHelper
  def title_link(str)
    name = Article.title
    name << str
    link_to h(name), article_path(....)
  end
end

viewでtitle_linkヘルパーが呼び出されるたびにリンク名がおかしなことになった。
1回目

<a href="..">xxのブログ aa</a>

2回目

<a href="..">xxのブログ aa bb</a>

3回目

<a href="..">xxのブログ aa bb cc</a>

Rubyは、破壊メソッドでなら定数でも警告なしに上書きできるんだけど、これによってArticle::TITLEがヘルパーを呼ぶたびに上書きされていた。
この部分。

  name << str

development環境では毎回ロードされるのでこのバグに気づかなくて、production環境でヒドいことになったのでした。