未分類

このブログを停止いたします

このブログの更新を停止し、新しくこたつつきみかん rev.2で再開したいと思います。理由を簡潔に列挙致します。

  • きっかけはブログデータ消失事件
  • 相対的なブログ記事の情報価値の低下
  • 以前の流れを断ち切って、新規一転して記事を投稿したい
  • 「わかりやすい情報」から「高度な情報」へ

このところ思っていたのは、もはや Objective-C の情報が少ない時代は終わりを迎え、本屋に行ったりググればすぐに日本語のわかりやすい情報が手に入るようになりました。わかりやすい情報を書き綴っていたこのブログの役目もそろそろ終わりとして良い頃合いでしょう。

それと同時に、もう一つ思ったのは、WEBにはわかりやすい情報やすぐに使える情報が溢れかえっており、より専門的な高度な情報だったり、正確な情報というのが今ひとつ見えてきません。英語で検索するといい文章が見つかることが多いのですが、日本語の検索結果はあまり満足していないのが現状です。

もうプログラムの基本的なことを語るのは十分でしょう。これからはより正確で高度な情報を配信していこうと思います。

このブログはずっと残しておくつもりですが、情報が古いので注意してください。また、しばらくしたらコメント欄を封鎖しようと思います。

いままでありがとうございました。

ブログデータ消失しました

さくらのVPS新プランに移行中、うっかり既存のプランの方のサーバーをセットアップしてしまい、ここ最近のブログデータと画像を消去してしまいました。

画像データはバックアップが無かったかもしれないので、現在どのようにするか検討中です。。。

古い情報はあまり役に立たなくなってきているので、そろそろ一度区切りを付けてもいいかもしれません。

今年はもっと記事書けるように頑張ります

新年、12月は記事を1エントリーも書かずに、ついに明けてしまいました。残念です。ここ最近、ブログの更新をサボっている感じになっていますので、月5エントリーペースで書きたいですね。

Objective-C のクイックリファレンスの方も、更新が途絶えてますが、今続きを書き始めているので、近日中に増えると思います。しかし、数ヶ月前から Interface Builder の記事を書きたくて仕方ないので、そちらを先に書き始めてしまうかもしれませんが。本当は、新しいXcodeが出てから書きたいのですが、なかなか出そうにないので、先に書いてしまう予定です。

Interface Builder に関する記事はとても少ない印象で、そして使っていない方が、もしかすると多数派なのかもしれないので、Inteface Builder のすばらしさを伝えられる記事にしたいです。

衝撃の温度グラフ

自宅サーバーの温度をモニターして24時間のグラフにしているのですが、この前面白い温度変化が見られたので、せっかくなので載せておきます。

グラフ

何が起きたのか不思議でしたが、家にいた人に聞いてみたところ、にわか雨降ったそうです。そして、サーバーのすぐ隣の窓から雨が吹き込んだらしい。

iPhone 4 を買おうと思います

ホワイトが欲しかったのですが、年内延期となると、今の 3G で年内までやっていくのは難しいのと、購入周期に影響が出るので、近々 iPhone 4 の黒いやつを買ってしまおうと思います。

ホワイトほしいなぁー。。。

雷の影響でサーバーが落ちてます

ここ2日連続、落雷の影響で停電し、サーバーの電源が落ちて、繋がらない状況が発生しております。この時期、まだまだ停電の余地がありますので、もし夕方アクセスして繋がらなかった場合、しばらく待ってからアクセスし直してください。

近日中にサーバーのメンテナンスを行います

近日中にサーバーのメンテナンスを行いますので、その間は閲覧ができなくなりますので、あらかじめご了承ください。

うちの自宅サーバーは、Mini-ITXで省スペースなものを作ったのですが、よくよく考えると、自宅が広いので全くMini-ITXに合わせたケースである必要がなく、大変な誤算だったと思っています。これから夏を迎えるにあたって、小さなケースではなく、大きなケースに変更し、もう少し放熱性が高そうな雰囲気にします。ファンも、その分もう少し大きく風量を持ったものを付けることができそうなので、ケースとファンの交換をします。

と、自作をしたことがない素人のお話でした。実際これでCPUの温度が多少下がるかが気になります。

最近ちょくちょくサーバーが落ちてます

自宅サーバーを立てて、早くも一年が過ぎました。夏に物理的な故障で落ちた時以外、あまりサーバーが落ちたことはなかったのですが、最近月に一回くらいのペースで落ちています。

前回落ちたときは、ログに crash という文字があったので、何かあったんだという事はわかりましたが、昨日から今日にかけて落ちていたのは、特にログを見ても何も残っていなかったので、原因が不明です。ログを探すのが甘いのかもしれませんが、今の私のスキルだと、この程度です。

来月も1回落ちるようでしたら、おそらくソフトウェアの障害だと思われるので、週1で再起動させるようにして、様子を見てみることにしてみます。

なぜ Objective-C は気持ち悪いのか – 完

なぜ Objective-C は気持ち悪いのか分析してみる企画。これまで、見た目やクラスについての気持ち悪さを考えましたが、最後に全体的に気持ち悪くしている要素を探ろうと思います。

参照カウンタ方式

Objective-C をはじめて最初に躓くのが、このメモリ管理だと思います。わかってしまえば、非常に簡単なルールで管理されていることが理解できるのですが、理解するのが少し難しく感じる方も多いようです。また、Javaの人から見ればガベージコレクションないの?C++の人から見れば、スマートポインタないの?なぜいまどき、煩わしそうな参照カウンタ方式を採用しているのだろうか、と思われることでしょう。しかし、実際には、それほど煩わしいものでもなく、ガベージコレクションよりはパフォーマンスはいいので、デメリットしかないわけではありません。2.0からは、ガベージコレクションを有効にもできます。

nilが無視される

NullPointerException の例外は有名です。Cでは、nullにアクセスするとセグメントエラーになったりします。 Objective-C ではどうでしょうか?なんと、nilにメッセージを送信しても、エラーにならないどころか、無視される仕様になっています。例えば、こんなコードを書きます。

NSString *s = nil;
NSLog( @"%@", [s description] );

何もなかったかのように、普通に実行されて終わります。実は、Objective-C では、nilにメッセージを送信したときの動作が決まっており、メソッドの戻り値が false の値をとるように実行されます。戻り値の型がidならnilで、戻り値の型がintなら0といったようにです。これは非常に気持ち悪く感じる方も居られるでしょう。なぜなら、エラーが発見しにくくなるからです。うまく実行できないと思ったら、オブジェクトがnilだったというようなことは、Objective-C においてはたまにあることです。

フレームワークが謎めいた動作をする

Objective-C とあわせて使われる Foundation フレームワークは、かなり不思議な動作をすることがあります。それはアプリケーションをデバッガで追ってみるとすぐにわかるでしょう。なんと、知らないクラス名がたくさん見えます。自分で生成した覚えの無いクラスがたくさんデバッガに写っていることでしょう。しかも、そのオブジェクトが、明らかに自分の生成したオブジェクトであったりすると、かなり気味の悪いことです。そう、Objective-C では表面上はドキュメント通りの動作をしているけれども、中を見てみると想像もできないような動きをしていることがあるのです。

NSString *s = [[NSString alloc] initWithFormat:@"string"];
NSDate *d = [[NSDate alloc] init];
NSNumber *n1 = [[NSNumber alloc] initWithInt:10];
NSNumber *n2 = [[NSNumber alloc] initWithInt:10];

例えば、これらのインスタンスの本当のクラス名は、実際とは異なります。これくらいなら、ドキュメントにも書かれているのですが、もっと複雑なプログラムを組んでいると、いつの間にか変なクラスを操作していることがあります。また、興味深い点としては、n1とn2は全く同じインスタンスを指す点です。NSNumberは、同じ値の場合、同じインスタンスを返すような動作をします。不思議ですね。alloc,initメソッドの定義は、面倒なだけではなく、このような動作をさせたいときに使えるのです。必ずしも、自分が期待する動作をしているわけではないことに注意すべきです。表面上は、そのようになっているということが、Objective-Cにおいては多々あります。

まとめ

ぱっとあげてみると、これくらいのことが思いつきました。この他にもまだまだ、 Objective-C が気持ち悪く感じる点はあるかと思います。

これまでの3回の記事で、Objective-Cが気持ち悪い理由を考えていましたが、正確に言えば、気持ち悪く思われそうな理由を考えていました。なぜなら、私はひとつも Objective-C を気持ち悪いだなんて思っていないからです。メッセージ式ひとつをとっても、オブジェクト指向のメッセージングを適切に表現した形に見えす。

私が Objective-C に惹かれたのは、その素直なオブジェクト指向の実現の仕方にあります。 Objective-C のオブジェクト指向は、純粋にオブジェクト同士の対話であり、すべて動的に行われます。私が Objective-C で最も気に入ってる点は、その書き味の良さです。思ったとおりのコードを、すばやく書くことができます。それは、 Objective-C の動的なものからくるゆるさというものも、少なからず影響していると思います。

過去2回のリンク

libavcodec / libavformat を使ってみる 1

ちょっと特殊なエンコード処理をしてみたい気分だったので、ffmpegを参考に、libavcodec, libavformat あたりを使ってみることにしました。

とりあえず今日は、動画ファイルのコーデック名を出力するようなプログラムを組んでみました。

Mac OS X で開発した場合は、MacPortsで ffmpeg をインストールし、XCodeの新規プロジェクトで Command Line Tool C で作成します。そのあと、プロジェクトの設定のビルドのタブで、ヘッダ検索パスに Ports でインストールしたヘッダなどが含まれる /opt/local/inculude あたりを設定し、プロジェクトに libavcodec.a と libavformat.a を加えるとビルドできるようなるはずです。

まず、ヘッダをインクルードします。libavcodec, libavformat は、次のヘッダをインクルードすると使えます。

#include <avcodec.h>
#include <avformat.h>

libavcodec, libavformat を使うプログラムでは、最初に av_register_all() を呼び出して、初期化します。

av_register_all();

今回は、ファイルの情報を調べたいので、av_open_input_file() を使って、ファイルの情報を得ます。この関数で得た AVFormatContext 構造体に、たくさんの情報が入ります。ここで得た AVFormatContext は、不要になったら av_close_input_file() で解放する必要があります。必要な引数は第二引数までで、動画のフォーマットを強制したい場合などに以降の引数は使用します。今回は自動判別して欲しいので、第三引数からは何も指定しません。

AVFormatContext *format;
if ( av_open_input_file( &format, filename, NULL, 0, NULL ) ) {
	puts( "Couldn't open file" );
}

次に、 av_find_stream_info() を使ってストリームの情報を付加します。

if ( av_find_stream_info( format ) < 0 ) {
		puts( "Couldn't find stream information" );
		return -1;
	}

ストリームの情報も得られたところで、各々のストリームのコーデックを出力します。

for ( int i = 0; i < format->nb_streams; i++ ) {
	printf( "stream #%dn", i );
	printf( "tcodec type: %dn", format->streams[i]->codec->codec_type );

	enum CodecID codec_id = format->streams[i]->codec->codec_id;
	AVCodec *codec = avcodec_find_decoder( codec_id );
	if ( codec ) {
		printf("tcodec name: %sn", codec->name );
	} else {
		printf( "tcodec id %d is not foundn", codec_id );
	}
}

format->nb_streams にストリーム数が書かれているので、その分だけ情報を出力します。 各ストリームの情報は、format->streams に入っています。AVStream 構造体の配列になっています。そしてその中の codec がコーデックの情報を表わしており、それは AVCodecContext 構造体です。この中のコーデックIDを得ることにより、IDから avcodec_find_decoder() を用いてデコーダを得ることができます。デコーダには、そのデコーダのコーデックの情報が入っていて、そのコーデックの名前も得ることができます。こうして、デコーダからコーデック名を得ることができるわけです。

このあとに、上で得たデコーダのコンテキストから、実際のデコーダを生成すれば、ストリームをデコードすることができるわけです。

サンプルソース: main.c

参考文献:
http://www.inb.uni-luebeck.de/~boehme/using_libavcodec.html
svn://svn.ffmpeg.org/ffmpeg/trunk ffmpeg