<< Prev Page Next Page >>

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書く事で広告が消せます。


マルチスレッドの反省

お仕事でiPadアプリを作った。画面をいろいろ操作してる間にも裏でスレッドが走ってて定期的にどのファイルをダウンロードするか判定して必要なファイルをダウンロードしたりするやつ。それだけなら別になにも難しくないんだけど、ファイルごと+ファイル群ごと+全体の3種類のプログレス表示とダウンロードが終わったら画面表示をがさっと変更する仕様があったのを甘く見てた。



ダウンロードだけでなくXMLを読み込んでDBに登録したりとかいろいろしてからイベントが上がって画面表示を変更するような作りにしてしまったため、出るわでるわEXC_BAD_ACCESS。

アニメーションして画面遷移したあとイベントリスナを解除してからUIViewControllerをreleaseし終わってるのに、ダウンロードスレッドのほうでイベントループの途中になってしまっているため、zombieオブジェクトに対するメッセージになってしまってEXC_BAD_ACCESSであぼーん。そらそうなるわな。

この程度の設計で間違うとはまだまだだ自分。

反省として、次回こういうものを作る機会があったらこういうつくりにすること、というのを備忘録として書いておこう。

[大方針]
・バックグラウンドスレッドから呼ばれるイベントリスナで画面に関わるAPIを呼ばない。iOSアプリはアニメーションによる遅延実行が多いのでハマる原因になる。
・挙動がカクカクしないよう、負荷を増やさないよう、@synchronizedの箇所を最小限にする、というか、意味的にatomicでなければならないことを表現する以外で@synchronizedを使わない。

[小方針]
・イベントリスナの処理ではModelを変更したり変更フラグをたてたりするだけにする
・画面描画が必要な場面ではNSTimerで0.1秒ごととかの定期実行スレッドを一つ動かしておいて、変更フラグを見て描画範囲を確定して、Modelのデータを取得して表示する。このときModelが変更途中の場合は待つのではなくスルーして次回定期実行時に参照すればよい。
・バックグラウンドスレッドが無駄に増えて行かないように、あらかじめダウンロード用ワーカスレッドを2つとか立ち上げておいて、ダウンロード開始するときはそのスレッドに依頼するようにする
・イベントリスナの処理中でイベントリスナの追加削除を行わない
・SQLiteのコネクションはopenしっぱなしでシングルトンを使い回す
・DBのトランザクション処理だけは@synchronizedで囲む

もう一度結城浩さんのマルチスレッドデザインパターンを読む。


じわじわと

タグの閉じ忘れをチェックするブックマークレットが便利。 - バニデザノート
タグの閉じ忘れチェックブックマークレットのはてブ数が増えていっているようで、便利なものつくっとくと放っておいても誰かが見つけるらしいという知見が得られています。

どうもご紹介ありがとうございます。
ブラウザのバージョンが上がっていくなかでどこで使えなくなるかヒヤヒヤしながらも、将来使えなくなっても直す気はあまりないという放置状態ですが、ユーザが多ければソースコードを勝手に変更して公開してくれる人も現れるはずと期待している他人本願。がんばれインターネッツ!

(追記2011/12/9)いまごろ気がついたChrome拡張機能としてリメイクされている、すごいぞインターネッツ。
HTMLタグの閉じ忘れをチェックするChrome拡張機能を作ってみた


jQueryイディオム:テーブルの行クリックでチェックボックスにチェック入れる

行ごとクリッカブルにするというのをもう少し改善?してみました。全然知らない人にツッコミいれてすみません。はてブで新着に出てたのでつい。

jQueryでテーブルの行ごとクリックして チェックボックスにチェック出来るよう にするTipsです。ユーザーがデータを 見ながらフォームを送信する際に、分か りやすくしてあげよう、という目的です。 行ごとクリッカブルにする、みたいな感じ。 jQueryでテーブルの行ごとクリックしてチェックボックスにチェックを入れられるようにする - かちびと. net
Chrome Google提供の高速ブラウザ。エクステンション豊富。 ★★★★★
Firefox 人気の火狐。アドオンが魅力的過ぎ ★★★★★
Safari Mac標準。iPhoneの登場でシェアは伸びるのか? ★★★★☆
Opera 目立たないけど実は高性能。もうちょい人気出てもいい ★★★★☆

改善点は以下です。

  • 「find()」メソッドと「:checkbox」セレクタ便利
  • 「hover(over,out)」メソッド便利
  • チェックボックスをクリックしてもちゃんと選択できるよ
  • どうせなので選択状態を行全体の色で表現

こういうスクリプトと

$(function() {
  $('.data tr').hover(function() {
    $(this).addClass('hover_tr');
  }, function() {
    $(this).removeClass('hover_tr');
  }).click(function(evt) {
    var $t = $(this);
    var chk = $t.find(':checkbox')[0];
    if (evt.target != chk) {
      chk.checked = !chk.checked;
    }
    if (chk.checked) {
      $t.addClass('checked_tr');
    } else {
      $t.removeClass('checked_tr');
    }
  });
});

こういうスタイルシートで実現しています。

.main_txt .data {
  border-collapse: collapse;
}
.main_txt .data td {
  border:1px solid black;
  padding: 4px 10px;
}
.main_txt .data .hover_tr td {
  background-color: #f0f0f0;
  color: #333;
}
.main_txt .data .checked_tr td {
  background-color: #0033aa;
  color: white;
  border:1px solid white;
}

いじょ!


プログラマとしてマシになるのに大事なこと

プログラマとしてやっていく(やっていかせる)ことについて、いつも考えてるけど難しいんだよね。

ただ、その中で、ひとつ変わらない大事なことがあります。

プログラマにとって大事なことは「プログラムが組めること」です。

言語を含めて、ツールが使えることが大事というわけではないということです。ライブラリのありかや使い方などを知っていることは大事ではありません。

もちろん、少なくともひとつの言語がちゃんと使えることは大前提です。
プログラマになるための勉強をしている人の前で話をしてきた - きしだのはてな
プログラマとしてやっていくのに大切なことってなんだろう。

逆に、何がないとプログラマとしてやっていけないんだろうと考えてみる。

ていうか、プログラマとしてやっていくってどういう状態を指すことにしようかと戻ってみる。

面倒になって終了…いやそうじゃなくって。


プログラマとしてやっていく、じゃなくて、もうちっとマシなプログラマになるにはどうしたらいいのか。何がないとマシになれないのか。という事を書いてみよう。

やっぱり勉強だよね。それも学ぶ技術が超必要。

学ぶ技術、とは、「学びたいのです。先生、教えてください。」とするのも本質的なところではそうなんだろうけど、もっと小手先の所でいくと、どこかからパクった技術を再構築して自分の知識体系の中に矛盾なく取り込むことだと思う。

プログラマの仕事は毎日毎日、知らないことやったことないことを調べたり考えたりしてどうにかこうにか解決したりしなかったりパクったり諦めたりの繰り返し。問題はそのパクりでもなんでもいいんだけど、解決を「学び」に直結できるか。

解決=学びにできるなら、解決のスピードが速くなればたくさんの問題を解決できてたくさん学べてもっとマシになる。たくさん知ればよりたくさんの問題を発見できてより深く学べるから知識は雪だるま式に増えていく。

そして、一つの問題を解決する途中で付随する小さな問題たちを面倒くさがらずに一つ一つきちんと解決して知識体系に組み込むことで、雪だるまの成長はもっともっと加速する。

さらにそれをブログやTwitterでアウトプットすることでより加速する可能性もある。(しない場合もある。ソース俺)



以前からずっと、「小さな問題は小さく解決するんだ」って言い続けている。

たとえば大きなアプリを作ってるときに、HTTPS通信でパスワード付きのSOCKSプロキシを通さなきゃいけなくなって、そのやり方は調べなきゃわからないってときに、そのアプリの通信部分をいじってパスワード入力ダイアログ出すように作って全体をビルドするとかサーバーにデプロイするとかして、ログイン画面からたどって2,3クリックしてその場面にたどり着いて、なんていうアホな開発はやめようって言い続けている。

そんなん、小さな1ファイルのコマンドラインツールかなにか、つくるでしょ。それでパスワードなんかソースコードにベタ書きしていろいろパラメータ変えたりして、何度も何度も実行したりして、一番効率よくて一番行儀良い方法を探ってから実際のアプリにコピペするでしょ。それで、あとでその辺の問題が起こったらその小さなコマンドラインツールが問題の切り分けに役立ったりしてハラショーでしょ。

もっと小さな例でいうなら、たとえばPHPの比較演算子がどう動くか調べるとか、SciTEとかでさくっと動かして調べればそれでいいのに実際のアプリ上で起こってることから類推するとか意味がわからんでしょ。


…(泣)


「もっとプログラミングの勉強してくださいお願い」って言うとき、必ずしも本を買えとかセミナー受けろとかそういうことだけとは限らないんだけどなあ(もちろんそういう体系的に学ぶこともとても良いことなんだけど)。プログラミングの仕事が忙しくて勉強ができないって思っちゃってる人がいたりして、そうじゃないんだけどなあ。それじゃいつまでたっても上手くならなくて簡単なことに時間かかりすぎてずっと忙しいままなんだけどなあ。


自発的に学べない人はやっていけないんだと思う。さらに、経験から学べない人はやってけないんだと思う。
最近年齢とともに学ぶ力が少し減退しているのを感じる。いつまでやっていけるんだろうかね。


好かれる利他的

そりゃそんなの嫌われるだろ。と思ったので。

ワシントン大学の心理学の実験。

実験に参加した者は心理学専攻の学部生たちで、コンピューター・ネットワークを介して他の学生4人と一緒に、あるゲームをするよう求められた。この「他の学生4人」というのは本当は実在せず、コンピューターのプログラムによるものだった。

ゲームでは、参加者1人1人が(実在のプレイヤーも架空のプレイヤーも)、1ラウンドごとにポイントの貯えを与えられる。これらのポイントは、手元に取っておいてもいいし、チームの共有財産として提供しても良い。

チームに差し出したポイントは、額面が2倍になる。参加者はその後、他の4人から供出されたポイントのうち、4分の1までを引き出して個人の貯えに加えることが認められる。ただし、共有財産にポイントを残しておくことで、グループ全体にボーナス点が付く可能性が増すと説明され――ボーナス点の詳細は説明されない――、引き出すポイントを4分の1未満に抑えることが推奨される。ゲームが終了した時点で、参加者たちはそれぞれ、ポイントを実際の商品券に交換できる。
「利他的な人」は嫌われる:実験結果 « WIRED.jp Archives
で、ややこしいからまとめると、
  • 被験者には5人でやるゲームって言うけど実は被験者以外の4人はロボ
  • ロボのうち一人は妙に自分勝手で自分だけ得しようとする
  • 一人は妙にわざわざ損してみんなに得させるような行動をする
さて被験者はどのプレイヤーと次も一緒にゲームしたいか聞いてみた。

自分だけ得しようとするヤツとは当然みんなやりたくないって言う。でもわざわざ損しようとするヤツともやりたくない、と半分以上の人が答えたらしい。
その理由は、「あの人のせいで自分が悪く見える」とか、あの人はルール違反をしているというものだった。利己的でないプレイヤーに、何か裏の目的があると疑う参加者もいた。
「利他的な人」は嫌われる:実験結果 « 2 « WIRED.jp Archives
そりゃそうでしょ。面白いほうの発言「あの人のせいで自分が悪く見える」がとりあげられているけど、ほとんどの人はそういうことじゃなくて「なんか薄気味悪い」と感じたんだろう。行動様式が意味不明だから。自分からわざわざ損しにくるとか、なんか怪しいし、アメリカ人が好きな「フェア」にも合致しない。

また、この実験で、「ボーナス点」というのが実際に加算されていたら、反応は違っただろう。その人のおかげでみんなでどーんと得ができたなら次もその人と一緒にやりたい、と思っただろう。


好かれる「利他的」、もしくは社会や組織が求める「利他的」っていうのは、自分からわざわざ損するだけではなくて、こういう経済ゲームであれば、目先の得をあえて取らないことによりみんなでもっと大きな得をとって自分も得をする、という行動様式であるはず。MMORPGでいえばつまんない壁役回復役をあえて引き受けることでみんなが自由に行動できた結果得られる経験値も多くなる、みたいな(ほんとか?)。

こういう実験結果がでたから「利他的は嫌われる」とか思って引っ込んじゃう人は意気地無し。


allocしてinitしてautoreleaseするメソッド

Objective-Cで任意のクラスに好きなメソッド生やせるってわかってから一気に気持ちが軽くなってCocoaでの開発が嫌じゃなくなってきた。いいよねiPad。いいよねiPhone。

View操作とか文字列操作のメソッド名が単に長いってだけのことにこんなに影響受けてたのかと驚く。考える内容が考えるのに近いスピードで打てない苦痛にこんなに弱いと思わなかった。人間やってみるといろんなことがわかるもんだ。なんかこう、重い足かせ手かせがついてるみたいな気持ちでいっぱいだったんだもの。

Objective-Cで無名カテゴリでprivateなプロパティを実現する方法 | Eudyptes Chrysocomeとかを利用して、retainとかreleaseとか自分でできるだけ書かないんだって決めて、でもそうすると今度はautoreleaseとか書くのが長くてちょっとウザ、となってくる。

self.label = [[[UILabel alloc]init]autorelease];
label.text = @"foobar";

そこでまたオレオレメソッド登場ですよ。(やりすぎ注意)

NSObject_Util.h

@interface NSObject(Util)
//allocしてinitしてautoreleaseして返す
+(id)uNew;
@end

オレオレメソッドは決まったプレフィックスつけてちょっと変な名前にしておこうオレルール。

NSObject_Util.m

#import "NSObject_Util.h"
@implementation NSObject(Util)
//allocしてinitしてautoreleaseして返す
+(id)uNew {
return [[[self alloc]init]autorelease];
}
@end

Objective-Cのselfはクラスとか実装オブジェクトではなくレシーバなので、これでちゃんと使えちゃうのが他の言語とちょっと違って面白い。
self.label = [UILabel uNew];
label.text = @"foobar";
self.button = [UIButton uNew];
self.myobj = [MyClass uNew];


「きれいごと」で大見得切って欲しい

次の総理大臣は野田さんになったということで、久しぶりに「社会」タグのことも書くよ。

まずは第一感想としては「前原さん、海江田さんじゃなくてよかったんじゃない」という。だって前原さん、危なすぎるでしょ!あの方は是非大臣、それもできるだけ海外との利害が対立しない分野で力を発揮して頂きたい。海江田さんはもうへとへとに疲れてそうだし。

で、かねてから、もうこの国の政治のダメダメさ加減にうんざりなわけなんだけど、そもそも震災とか起こる前から不景気で経済構造がヤバい状況に突入していて自殺者数が毎年3万人以上、そもそも何十年も前から少子高齢化が進行しつつあったのに最後のチャンスだった団塊ジュニア世代の女性が出産できる年齢はもうそろそろ終わるのに結局なにもできず人口ピラミッドにピクリとも山ができないので20年後は暗い予想しか立たない、その間政治家のみなさんは…

衆議院議員って任期4年間だけど、最後の任期満了は1976年だそうですよ。大変だね解散ばっかりで。

選挙って忙しいんだろうね。もうみんな気になっちゃって気になっちゃって仕事が手につかないみたいだから選挙とかやめちゃえばいいんじゃないかな。どうせ今の形で選挙したって政策に民意が反映されることはほとんどないわけだし。

それか選挙戦の握手回りとか街宣車とか街頭演説とかバラマキとか接待とか(…は無いのか一応)全部禁止してテレビとラジオとネットでしか活動しちゃいけないことにして投票は地デジの4色ボタンかネットですることにしたらいろいろ捗るんじゃね?選挙期間は2週間ぐらいにしてその間フジテレビが独占で一日中ずーっと候補者の演説とか政策の分析とか過去の発言とか実績の評価とかやりつづければ売国呼ばわりも収まるし見たくなければ他のチャンネル見ればいいし一石二鳥じゃね?いや別に他の局でもいいけども。

あと、ウチの国の総理大臣って真っ正面の正論で大見得切っちゃいけない法律とかあるんだろうか。

東大アイソトープ総合センターの児玉先生みたいな、「子供たちの健康を守るためには疫学的な調査結果なんて待っていられない」「イメージングセンサの導入は我が国の民間が持っている技術ですぐにでもできる」要するにお国が無理矢理にでも民間企業を召し抱えて適切に分担させてすぐに除染作業や放射線検査を始めろという正論。

ああいう正論って本来総理大臣あたりがどーんとぶちあげて、やらされる企業は「えーっ」てなるけど正論過ぎるので表立って反対できないし、それ以外の民衆は「よく言った!いいぞ!」となって支持率が上がる、そういうもんだと思うのだけど。

「脱原発、新エネルギー」を前首相がとなえてみたけど、となえ方があちこちに気を遣って歯切れが悪いってのと、あとそれは本当にアリなのか?ってのと、ニヤニヤしてて気持ち悪いってので今イチ「いいぞ!」とならないのが残念なところ。

経済成長にしても少子化対策にしても震災復興+原発事故収拾にしても、そこに重点を置いて他を後回しにしても誰も文句を言えないド正論だと思う。高い理念を示すっていうのはつまり真っ正面からきれいごとで正論をぶちかますってことじゃないのかな。河野太郎さんが最近魅力的に見えてしまうのは、今胸を張ってきれいごとを言ってそれを押し通す人が彼しかいないからだよね。

「今派閥がどうの政党がどうの言ってる場合か!ウチの党もあなたの党も今日中に妥協して今月中に東北に10兆円つぎこむんだ」みたいな。いやそういう額だとそう簡単にならないのはわかってるんだけども、財務省がね、とかいろいろあるとは思うんだけども。

「きれいごとだけじゃ世の中動かせないんだよ」ってそんな基本的なことは知ってるんだけどさ、きれいごとを全然上に掲げられないってのも寂しい世の中だよね。


cocoaの長ったらしいメソッドにつきあわない

Objective-Cは既存のクラスに勝手にメソッド生やせるようになっているのを利用して、よく使う長ったらしい記述を短くすることにしてみた。

NSString


isEqualToString -> eq
stringByAppendingString -> plus
stringByAppendingPathComponent -> plusPath
lastPathComponent -> filename
lastPathComponent + stringByDeletingPathExtension -> basename
stringByDeletingLastPathComponent -> dirname
正規表現に最初にマッチした部分文字列を配列で返す -> match:pattern
正規表現にマッチした文字列の配列の配列を返す -> matches:pattern
これは。快適なんじゃね?もうね、Objective-Cの正規表現がウザすぎて死ぬので。
あとおまけ
NSLocalizedString(name, comment) -> res(name)
すごいしょっちゅう使うのに補完候補の先頭に出てこなくてたくさんタイプするのが面倒なので。

UIView、CALayer


frame.origin.x -> left
frame.origin.x + frame.size.width -> right
frame.origin.y -> top
frame.origin.y + frame.size.height -> bottom
frame.size.width -> width
frame.size.height -> height
サイズを変えずに移動 -> eMove:x :y
相対移動 -> eOffset:x :y
サイズだけ変更 -> eSize:width :height
他のViewと同じサイズにする -> eSameSize:view
親View一杯に広げる -> eFitToSuperview
左に寄せる -> eFitLeft
右に寄せる -> eFitRight
上に寄せる -> eFitTop
下に寄せる -> eFitBottom
フェードイン -> eFadein
フェードアウト -> eFadeout
他のViewと一緒にスライド -> eSlideWith:view :x :y
あら便利。あらあら。これは気持ちいい。

実際にどうやるかは、【コラム】ダイナミックObjective-C (8) カテゴリ - 動的なメソッドの追加によるクラスの拡張 | エンタープライズ | マイコミジャーナル参照。


XCode4のプロジェクトテンプレートが作れない!

XCode3では、自分がよく使うframeworkとか、よく使うマクロを予め定義したヘッダファイルとか、自分が整理しやすいディレクトリ構成とかをもったプロジェクトテンプレートをXCode上で作り込むことができて、それをプロジェクトの新規作成をするときに選択することが出来た。
仕組みはとても単純で、テンプレート中のファイル名とディレクトリ名とテキストファイルの内容を一切合切、
___PROJECTNAME___→プロジェクト名
___PROJECTNAMEASIDENTIFIER___→プロジェクト名のスペースをアンダースコアに置換した文字列
に置換するというものだった。

XCode4で、自分が作ったプロジェクトテンプレートが選べなくなっていたので、くそっと思って同じようにプロジェクトテンプレートを作ろうと思った。

調べた。

なるほど、XCode上ではテンプレートの編集はできない、と
TemplateInfo.plistファイルをごりごりいじって、と
TemplateInfo.plistが階層構造になって親を継承してるから、それを変更しようと思ったら親の定義を全部持ってきて・・・
AppDelegateクラスにメンバー変数を加えるには・・・
QwartsCore frameworkを加えるには・・・


ぷちっ。

できるかっ!こんな面倒なもんできるかっ!

そんなわけで、XCode3形式のテンプレートをXCode3のときみたいに一切合切文字列置換するrubyスクリプトを作った。プロジェクト新規作成画面で選択できないけど、これを使ってプロジェクト新規作成すればいいんだ。


# XCode3タイプのプロジェクトテンプレートを文字列置換して新しいプロジェクトを作成する
class Replacer
@srcDir
@dstDir
@projectName
@projectNameIdent

# エントリポイント
def main(templateDir, projectDir)
if !templateDir || !projectDir then
p "USAGE: ruby replacetemplate.rb (template dir) (project dir)"
return
end

if File.exist?(projectDir) then
p projectDir + " is already exists."
return
end

@srcDir = templateDir
@dstDir = projectDir
@projectName = File.basename(projectDir)
@projectNameIdent = @projectName.gsub(" ", "_")

p "processing " + @projectNameIdent + " ..."
Dir.mkdir(@dstDir)
processDir(@srcDir, @dstDir)
end

# 文字列置換
def tr(str)
return str.gsub("___PROJECTNAMEASIDENTIFIER___", @projectNameIdent).gsub("___PROJECTNAME___", @projectName)
end

# ディレクトリ処理
def processDir(src, dst)
puts "dir : " + src + "->" + dst
Dir.foreach(src){|item|
if item != "." && item != ".." then
srcPath = src + "/" + item
dstPath = dst + "/" + tr(item)
if File.directory?(srcPath) then
Dir.mkdir(dstPath)
processDir(srcPath, dstPath)
elsif File.file?(srcPath) then
processFile(srcPath, dstPath)
end
puts item
end

}
end

# ファイル処理
def processFile(src, dst)
puts "file : " + src + "->" + dst
of = open(dst, "w")
begin
File.foreach(src) {|line|
of.print(tr(line))
}
ensure
of.close
end
end

end

r = Replacer.new
r.main ARGV[0], ARGV[1]


くたばるCocoa

iPhone/iPadアプリつくってます。しんどいです。

Webに慣れたご老体にはマルチスレッドでアニメーションがガンガン走ってallocしたらreleaseしなきゃいけない環境はきつい。

いやそんなのはたいした問題じゃない、何よりも、Objective-Cの変態的な文法とCocoaの変態的なAPIにやられっぱなし。C#が懐かしいよう。

文字列を連結するのに

NSString* a = @"Hello! ";
NSString* b = @"World!";
NSString* c = [a stringByAppendingString:b];

って。長いって。

URLエンコードするのに
NSString* comp = @"文字列";
NSString* encoded = [comp stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

って。いやいやねーわ。

無名関数、クロージャ、そういうようなものの「blocks」の構文がまたイカス。
blocksを引数にとってメンバ変数として覚えておくっていうコードがどうしても覚えられない。つまりJavaScriptだと、
function MyClass(onClicked) {
this.onClicked = onClicked;
}
(略)
var m = new MyClass(function(str) {
// 処理
});

となるところ、Objective-Cだと、
@interface MyClass {
@private
void (^onClicked)(NSString* str);
}
- (id)initWithCallback:(void (^)(NSString*)func;
@end
(略)
@implements MyClass
-(id)initWithCallback:(void (^)(NSString*)func {
onClicked = [[func copy]retain];
}
@end
(略)
MyClass* m = [[MyClass alloc]initWithCallback:^(NSString* str) {
// 処理
}];
となる。blocksのメンバー変数宣言がなんか変じゃない?


あと、UIAlertViewとかUIActionSheetとかpresentModalナントカ(覚えられない)のアニメーションが走ってる間、presentModalナントカを呼んでも無視されて表示されないっていうの誰かなんとかしてください。アニメーションが終わるのを待つっていうコードが書けなくて困ります。じゃあと思ってアニメーションしないようにanimated:NOにしたらこんどは周りのViewのレイアウトがごそっと移動しちゃうのを誰かなんとかしてください。