Backnumber

June, 2006
May, 2006
April, 2006
March, 2006
February, 2006
January, 2006
December, 2005
November, 2005
October, 2005
September, 2005
August, 2005
July, 2005
June, 2005
May, 2005
April, 2005
March, 2005
Feburary, 2005
January, 2005
December, 2004
November, 2004
October, 2004
September, 2004
Augsut, 2004
July, 2004
June, 2004
May, 2004
April, 2004
March, 2004
February, 2004
January, 2004
December, 2003
November, 2003
October, 2003
September, 2003
August, 2003

- HMDT archive-
January, 2005

January 25

久しぶりに、シイラのビルドを。シイラ Nightly build 050125。

  • マルチモニタ時に、すべてのタブを表示したときの問題の修正。

マルチモニタにしていると、メインスクリーン以外で Tab Exposé が効かなかったので、その修正。うちにはモニタがなかったから、PowerBook にテレビをつないでテストしたよ。テレビでも、600x480 にすると、そこそこ使えるね。

他にも裏ではいろいろやっているけど、公開できるレベルに達していないので、また後日。

January 24

retain しない NSArray が欲しい

『問題です。Objective-C であるクラスがあったとして、そのクラスの作成されたインスタンスをすべて取得するにはどうしたらいいでしょう?』

プログラミングしていて、上のような問題にぶちあたった。始めは、すべてのインスタンスを登録するための NSMutableArray 作って、init で登録、dealloc で削除すればいいじゃーん、と考えた。だけどよく考えると、NSArray に突っ込んでしまうとそこで retain されるから、NSArray から削除しない限り dealloc が呼ばれない。だめじゃん。5 秒で頓挫。

何が悪いって、NSArray に入れたときに retain されてしまうのが、この場合は、問題。どこかに retain しない NSArray はないかー?

そんな Objective-C の前提を覆してしまうようなものはどこにもなかったので、別の策を考えた。

1. オブジェクトを retain、release しない、新しい NSArray を作る
2. NSObject の retain をスワップして、条件によっては retain しないようにする。
3. C の配列を使う

1. は、めんどくさいから、嫌。2. は、山のような副作用が考えられるから、無茶。3. が現実的か。でも、オブジェクトのアクセスに NSArray のメソッドが使えないのが辛いな。

そこで気づいた。オブジェクトの「ポインタの値」を配列に入れてやればいいんじゃないか?ポインタの値を NSNumber でくるんでやって配列に入れる。これなら、retain されるのは NSNumber であって、もとのオブジェクトじゃない。

コードは、こんな感じ。

(sample)
static NSMutableArray* _allInstances;

- (id)init
{
    self = [super init];
    
    [_allInstances addObject:
            [NSNumber numberWithUnsignedInt:(unsigned int)self]];
    ...
}

取り出して使うときは、こうすればいい。

(sample)
    id instance = (id)[[_allInstances objectAtIndex:0] unsignedIntValue];

あぁ、これだからポインタって好き。いくらでも融通が利く。美しくないけど。

ちなみにこのコードは、ポインタと unsigned int のサイズが同じだ、という前提になっている。これだと 64 bit 環境で困るかもしれない。正しくは、sizeof を使って大きさをチェックしてやること。

追記)

OgreKit の園部さんから、コメントをいただきました。曰く、Core Foundation の arrayCallbacks を使えば簡単時に実現できますよ、と。せっかくなんで、こっちに転載しておきます。(本人の訂正により、一部修正)

CoreFoundationを使えば簡単に実現できますよ。

例えば、下記のようにすればオブジェクトの追加・削除時にretainもreleaseもされないNSMutableArrayを作れます。(arrayCallbacksをいじるともっと複雑なカスタマイズもできます。)

sample
CFArrayCallBacks arrayCallbacks = kCFTypeArrayCallBacks;
    arrayCallbacks.retain = NULL;
    arrayCallbacks.release = NULL;

NSMutableArray *noRetainArray = (NSMutableArray*)CFArrayCreateMutable(
    kCFAllocatorDefault, 0, &arrayCallbacks);

なるほど!Core Foundation の Create 系の関数に付いている、callbacks 引数はこういう使い方があるわけね。気がつかなかった!これは素敵だ。こっちを使うことにしよう。

January 23

昨日は、WOMeeting に参加してきた。WOMeeting は、WebObjects のデベロッパの集まりで、さまざまなセッションがあったり、ドキュメント読みがあったり、という集まりだそうだ。実際に業務で使っている方が多いから、実践的な話が聞けて、そこはとても楽しかった。

個人的には、WebObjects は興味がとってもとってもあるけど使ったことがなかった。でも話を聞いてみると、やっぱりいーなー。楽しそうだなー。Cocoa とメソッドのネーミングルールが似てるから、とても雰囲気は入りやすいし。個人的には、WebObjects は Objective-C のままの方がうれしかったんだけどなぁ。(昔は WebObjects は Objective-C で書かれていたけど、いまは Java になっている)

うーむ。自宅で環境を構築したくなってきた。ちょうど Mac mini が出たから、自宅サーバならこれでまぁだいじょうぶだろうし。Apple Store で計算してみると、Mac mini + Mac OS X Server で 170,100 円なり。ま、買えない値段じゃないよな。Mac mini より Mac OS X Server の方が高いってのが、なんとも。

January 14

シイラ Nightly build 050114。引き続き、タブの改良実験。

  • タブにページの読み込み状況を表示。
  • Dock が横にあるときに、すべてのタブを表示したときの問題を修正。

まず、ページの読み込み状況の表示について。いままでは、ステータスバーで読み込み状況を表示していたけど、これは評判が悪かった。ステータスバーを隠して使っている人は、見えなくなるからね。Safari みたいにアドレスバーでやってくれ、という意見もあったけど、あんまりベタに真似するのもいやだし。

そこで、タブに表示してみた。こんな風に。

いままでタブでぐるぐる回っていたやつがあったので、その下に表示してみた。この方法のいいところは、いままでは最前面のページの状況しか分からなかったのが、すべてのタブの状況が分かるようになることだ。実際に使ってみると、複数タブの読み込み時の精神的なストレスが減ることが分かる。少なくとも、おれは減った。ビジュアルフィードバックの大切さが、身にしみたね。

January 13

VersionTracker に、iSurf とかいうブラウザが登場しているけど、これはシイラの名前とアイコンを変えただけのもの。

シイラの再配布条件は BSD ライセンスで、コピーライトさえ明記してあれば改変、再配布は自由。だから、iSurf でもなんでも別に構わない。BSD ライセンスにしたのは、シイラをもとにして、いろいろな機能を持ったブラウザが出てきたら嬉しいから。iSurf がこの後独自機能を持つかどうか、見守ることにする。ま、無理だろうけど。

その点、SunriseBrowser はとても面白い。こういうソフトの助けになったら、シイラのソースコードを公開しているかいがあった、というものです。

January 12

Macworld SF で、いろいろ発表されてたね。Mac mini 小さいな。いいなあ。iPod shuffle 小さいな。いいなあ。

個人的に注目していたのは、デベロッパとしてはやはり気になる、iWork。噂されていた通り、ワープロソフトである Pages とともに登場。とりあえずの印象では、よくも悪くも iApplication の範疇にとどまっている感じ。できるだけ手間をかけずに、見栄えのいいものを作るところに注力している。これなら勝てるな。

Expo やっている裏で、Tiger のツアーが公開。Tiger の見所を、QuickTime で紹介してくれる。非常に分かりやすくて、効果的なムービーだ。去年の暮れ頃に比べて、アピアランスが変わっているものが多い。とくに、Dashboard は激変。一見の価値あり。

もう 1 つ、Tiger ネタ。ADC の Tiger Developer Overview Series に、Working with Automator が登場。Automator の紹介と、Automator で使われる Action の作り方を簡単に解説している。

Automator とは、Tiger で登場する複数のアプリケーションなどを連携させて、自動処理を行うためのツール。Automator では、昔から UNIX で使われている、パイプの概念を中心に持ってきている。パイプの連結を GUI で行えるようにしたのが、Automator の最大の売りだ。これを理解するには、さっき紹介した Tiger ツアーの、Automator を見るのが手っ取り早い。とても分かりやすい。

Automator で使われる、パイプで使われる仕事の単位は、Action と呼ばれる。Action は、小さいバイナリらしい。提供する仕事ごとに Action を作成し、Automator アプリケーション上で並べて使う。たとえば、Safari を使って URL 先のページをダウンロードする Action とか、フォルダを zip で固める Action とかが考えられる。

Action は、AppleScript か Cocoa で書くことができる。それぞれ、呼び出しのメソッドが定義されていて、渡された入力をもとに仕事を行い、出力を作成して次の Action に渡すことになる。どっちの言語を使うかは、Action にさせる仕事のタイプによる。仕事のタイプには、3 つの種類が考えられるらしい。

1 つは、他のアプリケーションを利用するもの。たとえば、Safari 用の Action とか、Address Book 用の Action とか。このタイプでは、利用するアプリケーションと通信する必要がある。Safari とは AppleScript で行い、Address Book は API が用意されているから Objective-C が使えるでしょう。2 つ目は、Framework やシステムコールを利用するもの。これは Objective-C を使うことになるだろう。3 つ目は、値の変換をしたり、ディスクに書き込んだり、Action だけで仕事を行えるもの。これは AppleScript だけでも、Objective-C でも行える。

Action の作成は、比較的簡単にできそうだ。なかなか面白そう。

シイラ Nightly build 050112。

  • すべてのタブを表示した後に、ツールバーがおかしくなる問題の修正。
  • ブックマークバー、タブ、サイドバーで、ボタン長押しによるコンテキストメニューの表示に対応

Tab Exposé のバグフィックスと、長押しコンテキストメニュー。

January 10

シイラ Nightly build 050110。久しぶりに、新規機能実装。

  • 「すべてのタブを表示」を追加。

ウィンドウメニューか、タブのコンテキストメニューから、すべてのタブを表示することができる。どうやって表示するかというと、こんな風に。

一目瞭然だね。この中からタブを選べば、そのタブが最前面に表示される。

とりあえず、この機能を Tab Exposé って呼んでいる。Apple から怒られたら、変更することにしよう。

Tab Exposé のアイディア自体は、かなり前に、シイラ掲示板のタブスレッドの方で提案してもらっていた。たしかに、強力で分かりやすくてインパクトが大きいんだけど、技術的に難しそうだなぁ、ということで検討しつつも実装はできなかった。それがようやくめどがたったので、実験してみることにした。

今回のビルドでは、機能として、複数タブの縮小表示、縮小表示中でもページ読み込み、縮小表示からのタブ選択、を実装している。Exposé 中でもページを読み込むし、アニメ表示も動く。だから、タブの読み込み開始と同時に Exposé をすれば、タブが読み込まれていく様子を見ることができる。

あと、ショートカットキーは、環境設定のタブパネルから変更可能。

まだ実装していないものとしては、Exposé アニメーション、マウスがロールオーバーしたときのページタイトルの表示、とかがある。アニメーションは、パフォーマンス的に難しいかも。できれば本家 Exposé 並みの速度を実現したいんだけど。Cocoa からじゃ無理かなぁ。

縮小表示でリンクをクリックして別のページを表示させることは、実はできる。でもこれをやるととても混乱しそうなので、いまはできないようにしてある。

新しい機能なんで、まだまだ荒削りだ。フィードバックをもとに改良を続けるので、意見、提案のある方はよろしく。

技術的にどう実装しているかというと、試行錯誤した結果、けっこう簡単にできることが分かった。ポイントは 2 つ。1 つは Exposé 中のページの位置とサイズをどうやって求めるか。もう 1 つはページをどうやって表示するか。

まず、ページの位置決め。はじめは、本家の Exposé のシミュレーションを行おうとしたんだけど、難しい。はっきりいって分からん。プログラミングの問題というよりは、数学の問題だよなぁ。「互いに重なり合わない領域による、2 次元充覆問題」とてでもいうんでしょうか。これって、すでに研究されている領域なんでしょうか?

本物の Exposé はできないので、「Exposé する領域は、すべて同一サイズ」という前提をおいてみた。1 つのウィンドウ上のタブは、全部同じ大きさのはずだからね。これなら、簡単!けっこう、さくっと作れた。

次に、ページの表示。ページは、実は、WebView を縮小してそのまま配置している。

処理の流れはこうなる。まず、もとのウィンドウのタブから WebView を外す。次に、フルスクリーンサイズの透明ウィンドウを作る。そして、WebView をリサイズ、縮小して配置する。分かってみれば、簡単。WebView の縮小には、NSView の scaleUnitSquareSize: を使った。

これで実現できた。ただ、Cocoa だけで作っていると、どうしてもパフォーマンスが出ない。目標は本家の Exposé のパフォーマンスなんだけど、どうしてもそこには追いつけない。どうも、本家 Exposé は、アプリケーションとは別スレッドで動いているようだし。これには Core Graphics API を叩く必要があるのかな?

January 8

現在、タブの新たなブラウズ方法を実験中。

実験その1。

難しいんだよ、これ。

January 7

シイラ Nightly build 050107。

  • ページをひとつながりの PDF として出力する、「1 枚の PDF としてプリント…」メニューを追加。

ページを PDF で保存するには、「プリント」から「PDF で保存」を選んでもいいけど、これだと PDF がページに分割される。新しい「1 枚の PDF としてプリント」だと、分割されないひとつづきの PDF で保存される。また、プリントメニューよりも手軽(必要なダイアログの枚数が少ない)。

ちなみに、WebView が表示しているページを PDF として取得するには、

(sample)
NSView* documentView;
NSData* pdfData;
documentView = [[[webView mainFrame] frameView] documentView];
pdfData = [documentView dataWithPDFInsideRect:[documentView frame]];

って、やる。WebView から直接データを取るのではなくて、documentView を使うのがポイント。

背景を印刷するかどうかは、WebPreferences の setShouldPrintBackground: で。

January 6

シイラの新しいビルド、出します!久しぶりだ。Nightly build 050106 になる。

  • 複数タブを一度に開いたときの、マウスへのレスポンスを改良。

去年の暮れに引き続き、複数タブを開いたときのレスポンス改良に挑戦中。今回の修正は、読み込みに遅延をかける方法だ。

それぞれのリソースを読み込む前に、一瞬遅延をかける。今回は 0.5 秒にしてみた。このすきまを利用することで、シイラがマウス処理を行うことができるようにしてみた。ちなみに、最前面のタブでは、遅延はかけていない。たぶん、Safari もこの方法を使っているんだと思う。

マウスへのレスポンスはよくなったと思う。言い換えると、虹色ぐるぐるの時間が短くなったと思う。今回は、背面タブのレンダリング禁止機能は切っておいた。これも組み合わせると、さらに効果的になるかもしれない。

January 5

今日が、仕事初め。本格的に始動します。

まずは、シイラ。去年の暮れにやりかけだった、複数タブを開くときの挙動の解析の続きから。

ソフトウェアの改良を行うには、まず何が起きているのか、きちんと解析することが重要。ということで、複数タブを一度に開いたときに、どのように接続が行われているのかを知るために、接続監視ツールを作ってみた。

このツールを立ち上げておくと、現在の TCP/IP の接続状況を、逐次表示してくれる。だから、ブラウザで複数タブを開くと、どういう順序でつながっていくか、だいたい分かる訳だ。これを使って、シイラの場合、Safari の場合、Camino の場合、と比較していくと、なにか手がかりがつかめるかもしれない。

いろいろと眺めていたところ、どうもシイラの場合は裏にあるタブや、後で開けたタブの方が先に読み込まれてしまうような気がする。なんでだろう。

ちなみに、このツールのコードは、netstat を利用している。手で netstat を叩くのと、結果は変わりません。若干、こっちの方がレスポンスがいいかもしれないけど。

よかったら、試してみて。

Connection Monitor
ConnectionMonitor.dmg

January 1

あけましておめでとうございます。今年もよろしくお願いします。

さて、今年は、やりますよ!HMDT は、やります!ふふふ。本腰を入れる態勢が整いました。

シイラも、それ以外も、どんどんいきます!まずは、今年の前半は Tiger リリースという大きな山があるので、それを見据えていきます。Tiger のインパクトは、ほんと大きいのです。

ではでは。

Woodenships さんに、「2004 年のお世話になったアプリケーション」のブラウザ部門で、シイラを選んでもらいました。ありがとうございます。うれしいっす。シイラは、まだまだいきます。ほんとです。


[Home] [Download] [Archives] [BBS] [Cocoa Programming Tips 1001] [Core Foundation の秘密] [Safari Developer Center] [はじめてのブラウザのつくり方] [Sketch BP] [スクリーンセイバーを作ろう] [Objective-C 最適化] [Authorization API 完全理解] [Mac OS X Programming Books Review] [オブジェクト指向の言語比較論] [panther-dev]

mailto: mkino@xd5.so-net.ne.jp