Appbankでもentrypostman氏が寄稿してくれたBB2Cという2ちゃんねるリーダーBB2C、なんといってもそのレンダリングの早さに驚いている声が多いため、ある凄腕開発者にこのアプリの速さの理由について意見をいただきました。
この方はかなりの凄腕開発者なのですが、UITableViewで大きなデータをレンダリングということは未経験であり、今回のケースは実行ファイルの文字列を眺めてみた感想に留めており、ソースコードやNIBファイルを見ているわけではないので、今回は推測の域をでない内容になります。なお以下内容はAppbankがほとんど編集をかけております。
まずUITableViewを使っているのかどうかという点について調べてみる。UITableViewを使うにはUITableViewDataSource というプロトコルに従ったクラスを実装する必要がある。例えばブックマークの部分にはそれを使っていて、以下のようなメソッド定義が発見できる。「tableView:~」というのがそれにあたる。
-[UIBLBookmarksViewController tableView:numberOfRowsInSection:] -[UIBLBookmarksViewController tableView:didSelectRowAtIndexPath:] -[UIBLBookmarksViewController tableView:commitEditingStyle:forRowAtIndexPath:] -[UIBLBookmarksViewController tableView:canEditRowAtIndexPath:] -[UIBLBookmarksViewController tableView:moveRowAtIndexPath:toIndexPath:] -[UIBLBookmarksViewController tableView:canMoveRowAtIndexPath:]
これらの「tableView:~」というメソッドはこの部分にしか出現していない。従って、何かトリッキーな方法を使っているのでない限り、掲示板の表示には UITableViewは使っていないと思われる。
表示と画面へのタッチを管理するビューは ListViewEx だと思われるが謎なのは ListView というクラスがまた別にあること。
いったんListViewを作成した後で、高速版のListViewExを作ったということなのか?両者間に継承関係があるかどうかは不明。
このクラスのメソッドに rectOfItemAtIndex: というのが見られる。おそらくこれで書き込みごとの大きさを調べているのではないかと。
-[ListViewEx setHilightItem:]
-[ListViewEx hilightItem]
-[ListViewEx initWithFrame:]
-[ListViewEx initWithCoder:]
-[ListViewEx releaseLayers]
-[ListViewEx prepareLayers]
-[ListViewEx updateHilightMark]
-[ListViewEx items]
-[ListViewEx updateItem:]
-[ListViewEx setNeedsDisplay]
-[ListViewEx setNeedsDisplayInRect:]
-[ListViewEx cancelTouch]
-[ListViewEx rectOfItem:]
-[ListViewEx rectOfItemAtIndex:] // ←こいつだ!
-[ListViewEx findItem:]
-[ListViewEx setHilightRect:]
-[ListViewEx dealloc]
-[ListViewEx touchesBegan:withEvent:]
-[ListViewEx touchesMoved:withEvent:]
-[ListViewEx touchesEnded:withEvent:]
-[ListViewEx touchesCancelled:withEvent:]
-[ListViewEx convertToNormalizedCurrentPosition:]
-[ListViewEx normalizedCurrentPosition]
-[ListViewEx convertFromNormalizedPosition:]
-[ListViewEx pressed]
-[ListViewEx clickable]
-[ListViewEx setClickable:]
-[ListViewEx listViewDelegate]
-[ListViewEx setListViewDelegate:]
-[ListViewEx renderer]
-[ListViewEx setRenderer:]
-[ListViewEx setNormalizedCurrentPosition:]
-[ListViewEx feedbackSwipe]
-[ListViewEx updateTiles]
-[ListViewEx setItems:]
-[ListViewEx initInternal]
_OBJC_IVAR_$_ListViewEx.pressed
_OBJC_IVAR_$_ListViewEx.touched
_OBJC_IVAR_$_ListViewEx.hilightMark
_OBJC_IVAR_$_ListViewEx.touchBeginLocationInWindow
_OBJC_IVAR_$_ListViewEx.touchBeginLocation
_OBJC_IVAR_$_ListViewEx.cellLayerDelegate
_OBJC_IVAR_$_ListViewEx.cellLayers
_OBJC_IVAR_$_ListViewEx.clickable
_OBJC_IVAR_$_ListViewEx.hilightItem
_OBJC_IVAR_$_ListViewEx.items
_OBJC_IVAR_$_ListViewEx.renderer
_OBJC_IVAR_$_ListViewEx.listViewDelegate
以上、ソースコードや NIBファイルの中身が見られないので確証はないが、状況証拠(?)から独自のビューを作って高速にレンダリングしていると推測する。そして、クラス名やメソッド名、全体のクラス構成から、かなり経験のある開発者の作品ではないかと思う。
ということらしいです。最後に「iPhoneアプリの中身の覗き方」整理して教えてくれたので後学のためにこちらにもメモさせていただきます。
1. ダウンロードしたアプリは ~Music/iTunes/Mobile\ Applications に入っている。
2. 拡張子は ipa だが、これは実は zip ファイルなので、別のディレクトリにコピーして拡張子を変更すると展開できる。
3. 展開すると Payload/アプリ名.app というディレクトリができて、この中にリソースが入っている。
4. *.nib というファイルは実はバイナリ形式のプロパティリストなので、拡張子を plist に変更すれば Property List Editor で参照可能。XML形式に保存しなおせばテキストとして参照可能。
5. アプリ名のファイルが実行形式なので、$ strings < アプリ名のファイルとすると実行ファイル内の文字列がすべて参照可能。これで、どんなクラスとメソッドが定義されているかが分かる。 謎1: *.nib は NIBファイルの情報を持つはずだが、IBでは読めない。読めないように情報を落としているのだと思うが、確証はない。 謎2: png形式のボタンのイメージファイルが読めない。元のファイルに何か細工をしているようだ。