<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;DUUHSXY-cCp7ImA9WhRbFE8.&quot;"><id>tag:blogger.com,1999:blog-5191809332257264217</id><updated>2012-02-05T16:33:58.858+09:00</updated><category term="Python" /><category term="静的単一代入" /><category term="GCD" /><category term="didReceiveMemoryWarning" /><category term="Xcode" /><category term="アセンブラ" /><category term="I18N" /><category term="Localization Suite" /><category term="Mercurial" /><category term="GUI" /><category term="Chromium" /><category term="C++" /><category term="Shiboken" /><category term="Dropbox SDK" /><category term="LLVM" /><category term="Revlog" /><category term="ライブラリ" /><category term="clutter" /><category term="高階関数" /><category term="CFNetwork" /><category term="UTI" /><category term="Blocks" /><category term="Mac" /><category term="ATOK Pad" /><category term="ハッシュ" /><category term="QuickDialog" /><category term="サムネイル機能" /><category term="URLローディングシステム" /><category term="AudioQueue" /><category term="Cinder" /><category term="UIDocumentInteractionController" /><category term="ランタイムAPI" /><category term="拡張" /><category term="Zip" /><category term="バインディング" /><category term="コンパイラ" /><category term="マルチタスク" /><category term="メモリ警告" /><category term="クイックルック" /><category term="API" /><category term="plist" /><category term="カスタムURLスキーム" /><category term="統一型識別子" /><category term="PySide" /><category term="GitHub" /><category term="NSLogger" /><category term="iPhone" /><category term="NSObject" /><category term="統計情報" /><category term="%エスケープ" /><category term="Qt" /><category term="コンパイル" /><category term="safx" /><category term="SSA" /><category term="JavaScript" /><category term="V8" /><category term="Interface Builder" /><category term="メッセージ転送" /><category term="タグ機能" /><title>Safx</title><subtitle type="html" /><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://safx-dev.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://safx-dev.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>safx developer</name><uri>http://www.blogger.com/profile/13931453776402259724</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/-xmu-GKy-rZo/TY10GvG4LYI/AAAAAAAAAgo/2rul0qNef4Q/s220/%255Bsafx%255D%2B-%2B%25E3%2581%2595%25E3%2581%25B5%25E9%2596%258B%25E7%2599%25BA%25E8%2580%2585.jpeg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>48</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/blogspot/TFCRl" /><feedburner:info uri="blogspot/tfcrl" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;DU4CQ30_cSp7ImA9WhRUGU4.&quot;"><id>tag:blogger.com,1999:blog-5191809332257264217.post-6432543254135152733</id><published>2012-01-31T00:39:00.000+09:00</published><updated>2012-01-31T00:39:22.349+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-31T00:39:22.349+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="iPhone" /><category scheme="http://www.blogger.com/atom/ns#" term="I18N" /><category scheme="http://www.blogger.com/atom/ns#" term="Localization Suite" /><title>フリーの国際化ツールLocalization Suiteを試す</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-1BM6De2qNsM/TyaqDpTE_wI/AAAAAAAAAsw/vj_vn-xs5U0/s1600/loc00.png" imageanchor="1" style=""&gt;&lt;img border="0" height="138" width="320" src="http://3.bp.blogspot.com/-1BM6De2qNsM/TyaqDpTE_wI/AAAAAAAAAsw/vj_vn-xs5U0/s320/loc00.png" /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;フリーの国際化ツール&lt;a href="http://www.loc-suite.org/"&gt;Localization Suite&lt;/a&gt;の存在を最近知ったので、便利かどうか試してみることにしました。&lt;/p&gt;

&lt;p&gt;なお、この文書では例としてOS X 10.6.8環境下で、Xcode 4.2のプロジェクト作成時のテンプレートであるMaster Detailed Application (Story board未使用)をLocalization Manager 11.4などを用いてローカライズします。&lt;/p&gt;

&lt;a name='more'&gt;&lt;/a&gt;

&lt;h3&gt;インストール&lt;/h3&gt;

&lt;p&gt;&lt;a href="http://www.loc-suite.org/"&gt;Localization Suite&lt;/a&gt;からLocalization Suite.tbzをダウンロードします。&lt;/p&gt;

&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-DY4kXAuQCMk/TyaqD2LCcmI/AAAAAAAAAs4/Cjo2oDMJXsw/s1600/loc01.png" imageanchor="1" style=""&gt;&lt;img border="0" height="128" width="312" src="http://2.bp.blogspot.com/-DY4kXAuQCMk/TyaqD2LCcmI/AAAAAAAAAs4/Cjo2oDMJXsw/s320/loc01.png" /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;これを解凍し、作成されたフォルダLocalization Suiteをアプリケーションフォルダにでも入れればよいでしょう。&lt;/p&gt;

&lt;h3&gt;ローカライズ前準備&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Xcode 4.2のテンプレートであるMaster Detailed ApplicationのプロジェクトをStory board未使用で作成します。&lt;/li&gt;
&lt;li&gt;&lt;p&gt;プロジェクト内の適切な場所で次のようにして.stringsファイルを作成します。&lt;/p&gt;

&lt;p&gt;&amp;gt; genstrings -o en.lproj *.m&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;作成されたLocalization.stringsをプロジェクトに追加してLocalizationにJapaneseを追加します。&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/--nOo1G7INJo/Tyaqdp3-klI/AAAAAAAAAus/awwfcbDdhMs/s1600/loc01a.png" imageanchor="1" style=""&gt;&lt;img border="0" height="171" width="320" src="http://1.bp.blogspot.com/--nOo1G7INJo/Tyaqdp3-klI/AAAAAAAAAus/awwfcbDdhMs/s320/loc01a.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;ローカライズ手順&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Localization Managerを起動します。&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-uAS54z2_Dss/TyaqD8qqqkI/AAAAAAAAAtE/qboPCiiOKIQ/s1600/loc02.png" imageanchor="1" style=""&gt;&lt;img border="0" height="110" width="320" src="http://2.bp.blogspot.com/-uAS54z2_Dss/TyaqD8qqqkI/AAAAAAAAAtE/qboPCiiOKIQ/s320/loc02.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;[File] → [New] → [From Xcode Project...]を選択します。ローカライズプロジェクトを作成することになるのでプロジェクト名を指定して[Save]します。&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-zjcu1VVC33Y/TyaqEZUr7pI/AAAAAAAAAtU/QlFZGkwEivY/s1600/loc03.png" imageanchor="1" style=""&gt;&lt;img border="0" height="294" width="320" src="http://1.bp.blogspot.com/-zjcu1VVC33Y/TyaqEZUr7pI/AAAAAAAAAtU/QlFZGkwEivY/s320/loc03.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;読み込むXcodeプロジェクトを選択します。&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-zO-cudif8SQ/TyaqEm_TxOI/AAAAAAAAAtg/5HOs3sF91gE/s1600/loc04.png" imageanchor="1" style=""&gt;&lt;img border="0" height="283" width="320" src="http://2.bp.blogspot.com/-zO-cudif8SQ/TyaqEm_TxOI/AAAAAAAAAtg/5HOs3sF91gE/s320/loc04.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;なぜかLocalization.stringsが取り込まれないので左端中ほどにある [+] をクリック。&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-wbZ63trktwo/TyaqTOSqHnI/AAAAAAAAAts/VwW721AWY4E/s1600/loc05.png" imageanchor="1" style=""&gt;&lt;img border="0" height="282" width="320" src="http://3.bp.blogspot.com/-wbZ63trktwo/TyaqTOSqHnI/AAAAAAAAAts/VwW721AWY4E/s320/loc05.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;そして、Localization.stringsを選択し[Open]。&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-Z7RFURt8NRw/TyaqTSC4qCI/AAAAAAAAAt4/RGJ8q_xJv1Q/s1600/loc06.png" imageanchor="1" style=""&gt;&lt;img border="0" height="282" width="320" src="http://2.bp.blogspot.com/-Z7RFURt8NRw/TyaqTSC4qCI/AAAAAAAAAt4/RGJ8q_xJv1Q/s320/loc06.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;これでローカライズが必要なファイルがプロジェクトに含まれました。ここから日本語ローカライズを追加しましょう。左下の [+] をクリックします。&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-i_6We1dtqvM/TyaqToNLFII/AAAAAAAAAuI/jLzSND57tB8/s1600/loc07.png" imageanchor="1" style=""&gt;&lt;img border="0" height="282" width="320" src="http://2.bp.blogspot.com/-i_6We1dtqvM/TyaqToNLFII/AAAAAAAAAuI/jLzSND57tB8/s320/loc07.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ダイアログからjaを[Add]します (テキストボックスに入力すると候補が絞り込まれます)。&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-RaFRWzp6NRs/TyaqTwltqWI/AAAAAAAAAuQ/51vdKj3TPZ4/s1600/loc08.png" imageanchor="1" style=""&gt;&lt;img border="0" height="254" width="320" src="http://1.bp.blogspot.com/-RaFRWzp6NRs/TyaqTwltqWI/AAAAAAAAAuQ/51vdKj3TPZ4/s320/loc08.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;その後、右下の[Edit...]をクリックすると.locを作成して、Localizerが起動しますのでJapaneseの欄に翻訳を入力して保存します。&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-IFZildEN9AM/TyaqUE-8LmI/AAAAAAAAAuc/1c5_K5n7vCc/s1600/loc09.png" imageanchor="1" style=""&gt;&lt;img border="0" height="226" width="320" src="http://1.bp.blogspot.com/-IFZildEN9AM/TyaqUE-8LmI/AAAAAAAAAuc/1c5_K5n7vCc/s320/loc09.png" /&gt;&lt;/a&gt;&lt;/div&gt;
ちなみに、下に元の文字列に近い候補が出たりします。このスクリーンショットではiPhoneとiPadのxibで同じ文字列があるので表示されています。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Localization Managerのファイル(.ldb)とLocalizerのファイル(.loc)は完全に独立しているようなので、書き戻す必要があります。Localization Managerに戻り、[Edit...]の左の[Read In...]をクリックすると.ldbに書き戻されます。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;最後に、右下の[Synchronize]をクリックするとローカライズファイルが作成されます。Xcodeで実行して確かめてみましょう。&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-w2FMrPnJIfc/Tyatn2mvwpI/AAAAAAAAAvY/zPuRzeTXLFc/s1600/loc10.png" imageanchor="1" style=""&gt;&lt;img border="0" height="320" width="164" src="http://3.bp.blogspot.com/-w2FMrPnJIfc/Tyatn2mvwpI/AAAAAAAAAvY/zPuRzeTXLFc/s320/loc10.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;あとは、変更があるたびに[Rescan]して翻訳追加、[Synchronize]を繰り返します。&lt;/p&gt;

&lt;h3&gt;長所&lt;/h3&gt;

&lt;p&gt;Localization Suiteを使う利点は次のものが挙げられます。ほとんどの点は他のローカライズツールに言えることでもあります。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;似ているエントリの翻訳から自動翻訳できる (iPhoneとiPadで同じようなxibがあるときに便利)&lt;/li&gt;
&lt;li&gt;辞書が使える (今回は利用していませんが、表記揺れを防ぐことができるかも)&lt;/li&gt;
&lt;li&gt;追加・削除されたエントリのメンテナンスが自動的に行われる&lt;/li&gt;
&lt;li&gt;翻訳対象ファイルが複数あってもまとめて編集できる&lt;/li&gt;
&lt;li&gt;各翻訳言語ごとの翻訳状況が一覧で把握できる&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-lcYzrkaS9w8/TyaqeSpnSiI/AAAAAAAAAvI/JWv7dDfYo2c/s1600/loc11.png" imageanchor="1" style=""&gt;&lt;img border="0" height="320" width="218" src="http://1.bp.blogspot.com/-lcYzrkaS9w8/TyaqeSpnSiI/AAAAAAAAAvI/JWv7dDfYo2c/s320/loc11.png" /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;h3&gt;問題点&lt;/h3&gt;

&lt;p&gt;ここまで読んできて、良いことづくめのツールのように見えるかもしれませんが、次のように問題点も多く、私個人はこのツールを利用していません。&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;編集したLocalizerのファイルが取り込めないときがある&lt;/li&gt;
&lt;li&gt;SynchronizeするたびにXcodeプロジェクトのスキーマがおかしくなる&lt;/li&gt;
&lt;li&gt;ストーリーボードに対応していない&lt;/li&gt;
&lt;li&gt;ヘルプなどの情報が少ない&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;1.については、最初の1、2回はLocalizerファイルの[Read In...]が使えるのですが、それ以後は次のようなエラーが出て、使えなくなってしまいます。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Old Localizer files without bundles are no longer supported!
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Localizerなしでもそれなりに利用できるのですが、自動翻訳などの便利機能が使えなくなるので利用価値が半減してしまいます。&lt;/p&gt;

&lt;p&gt;以上、いろいろ問題点を挙げましたが結局のところ、私個人の翻訳対象が1言語/100キー程度ということでわざわざローカライズツールを使うまでもないという結論に逹したというのが大きな理由です。多言語翻訳や大量の翻訳が必要になったときに、また検討してみたいと思います。&lt;/p&gt;

&lt;h3&gt;まとめ&lt;/h3&gt;

&lt;p&gt;Localization Suiteの利用法や使用感を紹介しました。ちなみに、ローカライズツールはApp Storeにもいくつかありますので興味を持たれた方は試してみてはいかがでしょうか。&lt;/p&gt;

&lt;h3&gt;関連項目&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.loc-suite.org/"&gt;Localization Suite&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5191809332257264217-6432543254135152733?l=safx-dev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/g2Lufwc7-DHO10jY0ccFeEVbtGc/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/g2Lufwc7-DHO10jY0ccFeEVbtGc/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/g2Lufwc7-DHO10jY0ccFeEVbtGc/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/g2Lufwc7-DHO10jY0ccFeEVbtGc/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/TFCRl/~4/PCRfp8zIbxo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://safx-dev.blogspot.com/feeds/6432543254135152733/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://safx-dev.blogspot.com/2012/01/localization-suite.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/6432543254135152733?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/6432543254135152733?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/TFCRl/~3/PCRfp8zIbxo/localization-suite.html" title="フリーの国際化ツールLocalization Suiteを試す" /><author><name>safx developer</name><uri>http://www.blogger.com/profile/13931453776402259724</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/-xmu-GKy-rZo/TY10GvG4LYI/AAAAAAAAAgo/2rul0qNef4Q/s220/%255Bsafx%255D%2B-%2B%25E3%2581%2595%25E3%2581%25B5%25E9%2596%258B%25E7%2599%25BA%25E8%2580%2585.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-1BM6De2qNsM/TyaqDpTE_wI/AAAAAAAAAsw/vj_vn-xs5U0/s72-c/loc00.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://safx-dev.blogspot.com/2012/01/localization-suite.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CE8GR3c4fCp7ImA9WhRUE04.&quot;"><id>tag:blogger.com,1999:blog-5191809332257264217.post-29268135454617327</id><published>2012-01-24T00:33:00.001+09:00</published><updated>2012-01-24T00:33:46.934+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-24T00:33:46.934+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="GitHub" /><category scheme="http://www.blogger.com/atom/ns#" term="Python" /><category scheme="http://www.blogger.com/atom/ns#" term="Mercurial" /><title>Googleのバグ予測アルゴリズムのMercurial拡張を書いてみました</title><content type="html">&lt;table style="width:auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="https://picasaweb.google.com/lh/photo/uUKxXbEOoE__2z4htkmRVtMTjNZETYmyPJy0liipFm0?feat=embedwebsite"&gt;&lt;img src="https://lh3.googleusercontent.com/-q_fLZSLYxZE/Tu3IXqTzBRI/AAAAAAAAApo/c1MEGY555bM/s400/P7310073.jpg" height="300" width="400" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;昨年の&lt;a href="http://www.publickey1.jp/blog/11/post_193.html"&gt;Publickeyで紹介されていたGoogleのバグ予測アルゴリズムの記事&lt;/a&gt;を見て、簡単に書けそうな気がしたのでMercurial拡張を書いてみました。&lt;/p&gt;

&lt;a name='more'&gt;&lt;/a&gt;

&lt;h3&gt;コード&lt;/h3&gt;

&lt;p&gt;&lt;a href="http://safx-dev.blogspot.com/2011/05/mercurial.html"&gt;以前の自分の記事&lt;/a&gt;なんかを参考に書きました。GitHubに上げておきます。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/safx/hg-predict-bug"&gt;safx/hg-predict-bug - GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;あまりに単純すぎて正しく書けているのか少し不安です。&lt;/p&gt;

&lt;h3&gt;インストール&lt;/h3&gt;

&lt;p&gt;ダウンロードしたコードを適当な場所に置き、.hgrcに次のような風に追加します。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[extensions]
bugprediction=/path/to/predictbug.py
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;使いかた&lt;/h3&gt;

&lt;p&gt;hg predictでファイル名を指定してください。オプションはありません。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt; hg predict *.m | sort -rn 
2.88 DFFileListViewController.m
2.72 DFRestClient.m
2.27 DFDetailViewController.m
2.18 DFImageViewController.m
2.16 DFPasswordViewController.m
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;関連項目&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.publickey1.jp/blog/11/post_193.html"&gt;グーグルはコードの品質向上のため「バグ予測アルゴリズム」を採用している － Publickey&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://google-engtools.blogspot.com/2011/12/bug-prediction-at-google.html"&gt;Bug Prediction at Google | Google Engineering Tools&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://safx-dev.blogspot.com/2011/05/mercurial.html"&gt;Safx: Mercurial拡張の書きかたについて&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5191809332257264217-29268135454617327?l=safx-dev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/24EquiwdQBGSerB_pWDG6P2s8eI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/24EquiwdQBGSerB_pWDG6P2s8eI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/24EquiwdQBGSerB_pWDG6P2s8eI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/24EquiwdQBGSerB_pWDG6P2s8eI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/TFCRl/~4/jlhtZ6AFsmE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://safx-dev.blogspot.com/feeds/29268135454617327/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://safx-dev.blogspot.com/2012/01/googlemercurial.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/29268135454617327?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/29268135454617327?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/TFCRl/~3/jlhtZ6AFsmE/googlemercurial.html" title="Googleのバグ予測アルゴリズムのMercurial拡張を書いてみました" /><author><name>safx developer</name><uri>http://www.blogger.com/profile/13931453776402259724</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/-xmu-GKy-rZo/TY10GvG4LYI/AAAAAAAAAgo/2rul0qNef4Q/s220/%255Bsafx%255D%2B-%2B%25E3%2581%2595%25E3%2581%25B5%25E9%2596%258B%25E7%2599%25BA%25E8%2580%2585.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/-q_fLZSLYxZE/Tu3IXqTzBRI/AAAAAAAAApo/c1MEGY555bM/s72-c/P7310073.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://safx-dev.blogspot.com/2012/01/googlemercurial.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0IFQH4_fip7ImA9WhRVEk0.&quot;"><id>tag:blogger.com,1999:blog-5191809332257264217.post-5480146127819343251</id><published>2012-01-10T22:18:00.000+09:00</published><updated>2012-01-10T22:18:31.046+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-10T22:18:31.046+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="統計情報" /><title>2011年の人気記事一覧と統計情報</title><content type="html">&lt;a href="http://goo.gl/photos/MSzrruhWID" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="https://lh5.googleusercontent.com/-y-HY_zRH7dI/Tu25_hFt8lI/AAAAAAAAApU/J7Ry_lTbroQ/s512/PC299728.jpg"&gt;&lt;/a&gt;

&lt;p&gt;あけましておめでとうございます。2011年に本ブログの記事の中で人気のあったページや統計情報をまとめてみました。これらはGoogle Analyticsの情報に基づいています。&lt;/p&gt;

&lt;a name='more'&gt;&lt;/a&gt;

&lt;p&gt;2011年にアクセス数の多かったページは次の通りです。相変らず他のアプリケーションやサービスとの連携記事が人気があるようです。ここまで固定だとランキングする意味がない気がしてきました。&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;img class="none" src="http://lh3.ggpht.com/_XbtP-rrPvTg/TKWBAQRcnvI/AAAAAAAAALc/L1B7aPJyu1Q/s72-c/Screen%20shot%202010-09-30%20at%2019.56.57.png"/&gt;&lt;a href="http://safx-dev.blogspot.com/2010/10/iosurl.html"&gt;iOSで独自カスタムURLスキームを設定する方法について&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;img class="none" src="http://lh5.ggpht.com/_XbtP-rrPvTg/TKRHn5ilGHI/AAAAAAAAAKg/vovcA7_ZrlQ/s72-c/urlscheme_sample.png"/&gt;&lt;a href="http://safx-dev.blogspot.com/2010/09/iosurl.html"&gt;iOSでカスタムURLスキームを利用してアプリケーションを起動する方法について&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;img class="none" src="http://lh6.ggpht.com/_XbtP-rrPvTg/TLhyt0cu3II/AAAAAAAAAOo/InCRLssARKw/s72-c/viewmanagement.png"/&gt;&lt;a href="http://safx-dev.blogspot.com/2010/10/viewcontroller.html"&gt;ViewControllerにおけるビュー管理サイクルとメモリ警告シミュレーションによるアンロード処理について&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;img class="none" src="http://lh6.ggpht.com/_XbtP-rrPvTg/TOUO0P38ovI/AAAAAAAAASA/RhyOnZFNhf4/s72-c/q1a.png"/&gt;&lt;a href="http://safx-dev.blogspot.com/2010/11/uidocumentinteractioncontroller.html"&gt;UIDocumentInteractionControllerを用いて別アプリケーションを開くメニューを表示する方法について&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;img class="none" src="http://lh6.ggpht.com/_XbtP-rrPvTg/TOfrvv9IdsI/AAAAAAAAASY/3GquGg_Kd5A/s72-c/Screen%20shot%202010-11-20%20at%2022.04.13.png" /&gt;&lt;a href="http://safx-dev.blogspot.com/2010/11/ios_21.html"&gt;iOSアプリケーションを特定のファイル形式に対応させる方法について&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;img class="none" src="http://lh3.ggpht.com/_XbtP-rrPvTg/TN6EwhqesjI/AAAAAAAAARU/xA-HH8RkfSM/s72-c/P9199023.jpg"/&gt;&lt;a href="http://safx-dev.blogspot.com/2010/11/cfnetworkhttp.html"&gt;CFNetworkフレームワークを用いた入力HTTPストリームの作成&lt;/a&gt;
&lt;li&gt;&lt;img class="none" src="http://lh3.ggpht.com/_XbtP-rrPvTg/TNkL2CVt0vI/AAAAAAAAARM/86J2qHI5jIU/s72-c/PA036663.jpg" /&gt;&lt;a href="http://safx-dev.blogspot.com/2010/11/nsurlconnectionurl.html"&gt;NSURLConnectionを用いたURLローディングシステムによる通信&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;img class="none" src="http://lh6.ggpht.com/_XbtP-rrPvTg/TSSAukb_jYI/AAAAAAAAAWQ/XahvWXWhUpA/s72-c/xc02.png"/&gt;&lt;a href="http://safx-dev.blogspot.com/2011/01/xcode-325ios-40-sdk.html"&gt;Xcode 3.2.5にiOS 4.0 SDKを導入する方法について&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;img class="none" src="http://lh6.ggpht.com/_XbtP-rrPvTg/TKSdEyHWDEI/AAAAAAAAAK0/mhdVvQf2e0I/s72-c/ios_state.png" /&gt;&lt;a href="http://safx-dev.blogspot.com/2010/09/ios-4.html"&gt;iOS 4のマルチタスク処理における状態遷移について&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;img class="none" src="http://lh4.ggpht.com/_XbtP-rrPvTg/TM_s41Od5OI/AAAAAAAAAQ4/qdK-6UW5FhQ/s72-c/icon2.png" /&gt;&lt;a href="http://safx-dev.blogspot.com/2010/11/ios.html"&gt;iOSアプケーションにバンドルする画像リソースについて&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;ページビュー数の月ごとの遷移は次のようになりました。&lt;/p&gt;

&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-GMT4TI06N2k/Tww3ojZTEeI/AAAAAAAAAsE/HfK7av1t-eg/s1600/2011st.png" imageanchor="1" style=""&gt;&lt;img border="0" height="114" width="320" src="http://4.bp.blogspot.com/-GMT4TI06N2k/Tww3ojZTEeI/AAAAAAAAAsE/HfK7av1t-eg/s320/2011st.png" /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;年間ページビューのブラウザ別の割合は次のようになりました。Google Analyticsの結果だとIEがほとんどいないことになっています。&lt;/p&gt;

&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-1f6q3senhNc/Tww3o-OukeI/AAAAAAAAAsM/oR39uYXmTbM/s1600/Screen%2Bshot%2B2012-01-10%2Bat%2B22.02.29.png" imageanchor="1" style=""&gt;&lt;img border="0" height="320" width="159" src="http://4.bp.blogspot.com/-1f6q3senhNc/Tww3o-OukeI/AAAAAAAAAsM/oR39uYXmTbM/s320/Screen%2Bshot%2B2012-01-10%2Bat%2B22.02.29.png" /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;年間ページビューのOSバージョン別の割合は次の通りです。年間で見ると10.6とXPが多いですが12月のみのデータだと10.6と10.7が共に28%、XPが13%、7が12%となっており、移行が始まっているのがわかります。&lt;/p&gt;

&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-1DxUBwkUQ-I/Tww3o9x7p0I/AAAAAAAAAsc/xnb2EBtxxeo/s1600/Screen%2Bshot%2B2012-01-10%2Bat%2B22.02.22.png" imageanchor="1" style=""&gt;&lt;img border="0" height="320" width="118" src="http://1.bp.blogspot.com/-1DxUBwkUQ-I/Tww3o9x7p0I/AAAAAAAAAsc/xnb2EBtxxeo/s320/Screen%2Bshot%2B2012-01-10%2Bat%2B22.02.22.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5191809332257264217-5480146127819343251?l=safx-dev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/xU6Fw3SpqesnDAci61pmHRyqYSQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/xU6Fw3SpqesnDAci61pmHRyqYSQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/xU6Fw3SpqesnDAci61pmHRyqYSQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/xU6Fw3SpqesnDAci61pmHRyqYSQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/TFCRl/~4/n857HFlnjdA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://safx-dev.blogspot.com/feeds/5480146127819343251/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://safx-dev.blogspot.com/2012/01/2011.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/5480146127819343251?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/5480146127819343251?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/TFCRl/~3/n857HFlnjdA/2011.html" title="2011年の人気記事一覧と統計情報" /><author><name>safx developer</name><uri>http://www.blogger.com/profile/13931453776402259724</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/-xmu-GKy-rZo/TY10GvG4LYI/AAAAAAAAAgo/2rul0qNef4Q/s220/%255Bsafx%255D%2B-%2B%25E3%2581%2595%25E3%2581%25B5%25E9%2596%258B%25E7%2599%25BA%25E8%2580%2585.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh5.googleusercontent.com/-y-HY_zRH7dI/Tu25_hFt8lI/AAAAAAAAApU/J7Ry_lTbroQ/s72-c/PC299728.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://safx-dev.blogspot.com/2012/01/2011.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUYBQX85eCp7ImA9WhRXGUU.&quot;"><id>tag:blogger.com,1999:blog-5191809332257264217.post-3125899377868639655</id><published>2011-12-19T00:38:00.000+09:00</published><updated>2011-12-27T20:59:10.120+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-27T20:59:10.120+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="NSLogger" /><category scheme="http://www.blogger.com/atom/ns#" term="ライブラリ" /><category scheme="http://www.blogger.com/atom/ns#" term="iPhone" /><title>NSLoggerで手軽にログを取る方法について</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-DgMiqt908Rk/Tu4CVJdQnMI/AAAAAAAAArQ/MfKDmfewzQY/s1600/Screen%2Bshot%2B2011-12-19%2Bat%2B0.09.39.png" imageanchor="1" style=""&gt;&lt;img border="0" height="320" width="310" src="http://1.bp.blogspot.com/-DgMiqt908Rk/Tu4CVJdQnMI/AAAAAAAAArQ/MfKDmfewzQY/s320/Screen%2Bshot%2B2011-12-19%2Bat%2B0.09.39.png" /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://github.com/fpillet/NSLogger"&gt;NSLogger&lt;/a&gt;はiOSとOS X上で動作するロガーです。簡単に言えばNSLogの代わりとなるようなものですが、次のような特徴を持っています。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ログにレベルやタグを指定できる。&lt;/li&gt;
&lt;li&gt;画像をログに出せる。&lt;/li&gt;
&lt;li&gt;Mac OS X上で動作する専用ビューワで内容を確認できる。フィルタや検索も可能。&lt;/li&gt;
&lt;li&gt;専用ビューワでリモート接続されたアプリのログが表示できる (デフォルトでSSLを利用)。&lt;/li&gt;
&lt;li&gt;ログを保存して後で見ることができる。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;いろいろ多機能にも関わらず導入は簡単で、使いかたもNSLogと大差ありません。そこで、本記事ではNSLogger 1.0をXcode 4.2に導入する手順と、簡単な利用法を紹介します。&lt;/p&gt;

&lt;p&gt;なお、NSLoggerはARCに対応しており、BSDライセンスで提供されています。&lt;/p&gt;
&lt;a name='more'&gt;&lt;/a&gt;

&lt;h3&gt;ダウンロードとテスト&lt;/h3&gt;
&lt;p&gt;まずダウンロードしてサンプルアプリをコンパイルして動作確認を行います。&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;NSLoggerの&lt;a href="https://github.com/fpillet/NSLogger/downloads"&gt;ダウンロードページ&lt;/a&gt;からNSLogger 1.0.zipをダウンロードします。&lt;/li&gt;
&lt;li&gt;ダウンロードしたファイルを解凍し、NSLogger.appを/Applicationsにでも入れておきます。&lt;/li&gt;
&lt;li&gt;NSLogger.appを起動しておきます。次のようなステータスウィンドウが表示されるはずです。
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-5s8X5IfsGBA/Tu4A_tmSR1I/AAAAAAAAAp4/_mcksqqmVbE/s1600/nslogger1.png" imageanchor="1" style=""&gt;&lt;img border="0" height="194" width="320" src="http://1.bp.blogspot.com/-5s8X5IfsGBA/Tu4A_tmSR1I/AAAAAAAAAp4/_mcksqqmVbE/s320/nslogger1.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;ディレクトリExamples内にサンプルがありますのでコンパイルして実行します。&lt;/li&gt;
&lt;li&gt;Start Sending Logsをタップします。&lt;/li&gt;
&lt;li&gt;ログウィンドウが開き、ログが表示されていきます。
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-prOFxH72RCo/Tu4A_9WZROI/AAAAAAAAAqE/4FGpBV_IrOo/s1600/nslogger2.png" imageanchor="1" style=""&gt;&lt;img border="0" height="264" width="320" src="http://1.bp.blogspot.com/-prOFxH72RCo/Tu4A_9WZROI/AAAAAAAAAqE/4FGpBV_IrOo/s320/nslogger2.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;ログビューワの利用法&lt;/h3&gt;
&lt;p&gt;ログビューワNSLogger.appの利用法を簡単に紹介します。&lt;/p&gt;

&lt;p&gt;メインウィンドウを次に示します。右ペインにログが表示されます。ここには時間、スレッド、タグ、ログメッセージ、ログの画像が表示されていきます。&lt;/p&gt;

&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-QA9BgA9hCtc/Tu4BAQPGmTI/AAAAAAAAAqQ/6L3jXLNbmm0/s1600/nslogger3.png" imageanchor="1" style=""&gt;&lt;img border="0" height="261" width="320" src="http://4.bp.blogspot.com/-QA9BgA9hCtc/Tu4BAQPGmTI/AAAAAAAAAqQ/6L3jXLNbmm0/s320/nslogger3.png" /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;ステータスバーにある f ボタンを押すと各ログメッセージにファイル、行数、関数名などが表示されます。これは後で少しだけ紹介する、末尾に F が付いているログ関数を利用すると表示することができます。&lt;/p&gt;

&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-V_yj1ZNgiCY/Tu4BA0x1zrI/AAAAAAAAAqY/CCdFNmNu2gs/s1600/nslogger4.png" imageanchor="1" style=""&gt;&lt;img border="0" height="262" width="320" src="http://1.bp.blogspot.com/-V_yj1ZNgiCY/Tu4BA0x1zrI/AAAAAAAAAqY/CCdFNmNu2gs/s320/nslogger4.png" /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;右下は簡易フィルタです。レベル、タグで条件に当てはまるものだけ表示することができます。&lt;/p&gt;

&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-1mHolp5L3Jo/Tu4BBPc4yLI/AAAAAAAAAqk/YafmIeYSH2Y/s1600/nslogger5.png" imageanchor="1" style=""&gt;&lt;img border="0" height="244" width="320" src="http://1.bp.blogspot.com/-1mHolp5L3Jo/Tu4BBPc4yLI/AAAAAAAAAqk/YafmIeYSH2Y/s320/nslogger5.png" /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;左下はフィルタです。次の例は適当なものですが、このように関数名やログレベルを条件にすることができます。&lt;/p&gt;

&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-NqRzK99mfG0/Tu4BF9pSruI/AAAAAAAAAq0/3voigDuLI6k/s1600/nslogger6.png" imageanchor="1" style=""&gt;&lt;img border="0" height="183" width="320" src="http://2.bp.blogspot.com/-NqRzK99mfG0/Tu4BF9pSruI/AAAAAAAAAq0/3voigDuLI6k/s320/nslogger6.png" /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;h3&gt;アプリケーションへの導入&lt;/h3&gt;
&lt;p&gt;自分のアプリへの導入は次のような手順で行います。&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Add to your project/iOS - Mac OS X内にある次の3ファイルをプロジェクトに追加します。&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;LoggerCommon.h&lt;/li&gt;
&lt;li&gt;LoggerClient.h&lt;/li&gt;
&lt;li&gt;LoggerClient.m&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;次の2フレームワークを追加します。&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;CFNetwork.framework&lt;/li&gt;
&lt;li&gt;SystemConfiguration.framework&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;後は次の関数を呼ぶだけです。第1引数がタグ、第2引数がログレベル、第3引数以降がフォーマット付き文字列になります。&lt;/p&gt;
&lt;pre&gt;LogMessage(@"network", 0, @"なんかのエラー: %@", url);&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;基本API&lt;/h3&gt;
&lt;p&gt;NSLoggerの基本APIの一部を次に示します。&lt;/p&gt;

&lt;pre class="brush:cpp"&gt;void LogMessageCompat(NSString *format, ...);
void LogMessage(NSString *tag, int level, NSString *format, ...);
void LogData(NSString *tag, int level, NSData *data);
void LogImageData(NSString *tag, int level, int width, int height, NSData *data);
void LogMarker(NSString *text);
&lt;/pre&gt;

&lt;p&gt;LogMessageCompatがNSLogと同じようにメッセージを出力するものです。LogImageDataで画像を出力できたりします。詳細や他の関数などは&lt;a href="https://github.com/fpillet/NSLogger/wiki/NSLogger-API"&gt;NSLogger API&lt;/a&gt;を参照してください。&lt;/p&gt;

&lt;h3&gt;NSLogger.appの自動起動&lt;/h3&gt;
&lt;p&gt;Edit SchemeでRun MyApp.appのPre-actionsにopen -g -a NSLoggerと記述しておくことで、デバッグ時に自動でNSLogger.appが起動するようになります。&lt;/p&gt;

&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-nFh4AYobhlI/Tu4BGGiiaHI/AAAAAAAAArA/EgRVmq9JbTQ/s1600/nslogger7.png" imageanchor="1" style=""&gt;&lt;img border="0" height="218" width="320" src="http://3.bp.blogspot.com/-nFh4AYobhlI/Tu4BGGiiaHI/AAAAAAAAArA/EgRVmq9JbTQ/s320/nslogger7.png" /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;h3&gt;マクロの登録&lt;/h3&gt;
&lt;p&gt;NSLogのときと同様の方法でデバッグビルド時のみログ出力を有効にすることもできます。個人的には&lt;a href="http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/Level.html"&gt;Apache Log4jのログレベル&lt;/a&gt;を参考にしつつ、末尾に F が付いているログ関数を使って、MyApp-prefix.pchに次のように書いて用いています。&lt;/p&gt;

&lt;pre class="brush:cpp"&gt;#ifdef DEBUG
    #import "LoggerClient.h"
    #define XLOG_FATAL   0
    #define XLOG_ERROR   1
    #define XLOG_WARNING 2
    #define XLOG_INFO    3
    #define XLOG_DEBUG   4
    #define XLOG_TRACE   5
    #define XLog(tag,level,...)            LogMessageF  (__FILE__,__LINE__,__FUNCTION__,tag,level,__VA_ARGS__)
    #define XLogData(tag,level,w,h,data)   LogDataF     (__FILE__,__LINE__,__FUNCTION__,tag,level,    data)
    #define XLogImage(tag,level,w,h,data)  LogImageDataF(__FILE__,__LINE__,__FUNCTION__,tag,level,w,h,data)
    #define XLogMarker(text)               LogMarker(text)
#else
    #define XLog(...)         do{}while(0)
    #define XLogData(...)     do{}while(0)
    #define XLogImage(...)    do{}while(0)
    #define XLogMarker(...)   do{}while(0)
#endif
&lt;/pre&gt;

&lt;h3&gt;まとめ&lt;/h3&gt;
&lt;p&gt;NSLoggerの導入手順と簡単な利用法を紹介しました。&lt;/p&gt;

&lt;h3&gt;関連リンク&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/fpillet/NSLogger"&gt;fpillet/NSLogger - GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5191809332257264217-3125899377868639655?l=safx-dev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/pmP7UOtCeDLE6xvGW63LtJPA_oc/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/pmP7UOtCeDLE6xvGW63LtJPA_oc/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/pmP7UOtCeDLE6xvGW63LtJPA_oc/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/pmP7UOtCeDLE6xvGW63LtJPA_oc/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/TFCRl/~4/Bwdw13cr9Vw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://safx-dev.blogspot.com/feeds/3125899377868639655/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://safx-dev.blogspot.com/2011/12/nslogger.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/3125899377868639655?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/3125899377868639655?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/TFCRl/~3/Bwdw13cr9Vw/nslogger.html" title="NSLoggerで手軽にログを取る方法について" /><author><name>safx developer</name><uri>http://www.blogger.com/profile/13931453776402259724</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/-xmu-GKy-rZo/TY10GvG4LYI/AAAAAAAAAgo/2rul0qNef4Q/s220/%255Bsafx%255D%2B-%2B%25E3%2581%2595%25E3%2581%25B5%25E9%2596%258B%25E7%2599%25BA%25E8%2580%2585.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-DgMiqt908Rk/Tu4CVJdQnMI/AAAAAAAAArQ/MfKDmfewzQY/s72-c/Screen%2Bshot%2B2011-12-19%2Bat%2B0.09.39.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://safx-dev.blogspot.com/2011/12/nslogger.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkcGRnY8eyp7ImA9WhRQGEo.&quot;"><id>tag:blogger.com,1999:blog-5191809332257264217.post-2406622711151115127</id><published>2011-12-14T23:47:00.000+09:00</published><updated>2011-12-14T23:47:07.873+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-14T23:47:07.873+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="iPhone" /><category scheme="http://www.blogger.com/atom/ns#" term="Dropbox SDK" /><title>Xcode4.2でのDropbox SDK v1のサンプルアプリケーションのコンパイルについて</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-7SXgCw28IEw/TuizLKcC18I/AAAAAAAAAoc/x-5PgvOmCZA/s1600/db3.png" imageanchor="1" style=""&gt;&lt;img border="0" height="320" width="214" src="http://1.bp.blogspot.com/-7SXgCw28IEw/TuizLKcC18I/AAAAAAAAAoc/x-5PgvOmCZA/s320/db3.png" /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;以前の記事で&lt;a href="http://safx-dev.blogspot.com/2010/08/dropbox-sdk-for-ios.html"&gt;Dropbox SDKのサンプルアプリケーションをコンパイルする方法&lt;/a&gt;を紹介しました。&lt;/p&gt;

&lt;p&gt;あれから、Dropbox SDK v1がリリースされ、Xcodeも4.2になってサンプルアプリのコンパイル方法が多少変更されていますので、あらためてサンプルのコンパイル手順を簡単に紹介します。&lt;/p&gt;

&lt;a name='more'&gt;&lt;/a&gt;

&lt;ol&gt;
&lt;li&gt;事前にディベロッパキー(App-keyとApp-secret)を取得しておきます。詳細は&lt;a href="http://safx-dev.blogspot.com/2010/08/dropbox-sdk-for-ios.html"&gt;以前の記事&lt;/a&gt;を参照してください。&lt;/li&gt;
&lt;li&gt;Dropboxの&lt;a href="https://www.dropbox.com/developers/reference/sdk"&gt;ディベロッパサイト&lt;/a&gt;からiOS SDKをダウンロードします。&lt;/li&gt;
&lt;li&gt;dropbox-ios-sdk-1.0.zipを解凍します。&lt;/li&gt;
&lt;li&gt;ディレクトリexamples/DBRouletteからXcodeプロジェクトを開きます。&lt;/li&gt;
&lt;li&gt;&lt;p&gt;DBRouletteAppDelegate.mのapplication:didFinishLaunchingWithOptions:にapp-keyとapp-secretをセットします。&lt;/p&gt;

&lt;pre class="brush:cpp"&gt;-(BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  // アプリ起動前にいくつかの変数をセット
  NSString* appKey = @"App keyをセット";
  NSString* appSecret = @"App secretをセット";
  NSString* root = kDBRootDropbox; // kDBRootAppFolder か kDBRootDropbox のどちらか&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;認証方法が変更されているため、Info.plistのURL Schemesを設定します。スキーマ名は「db-&lt;App key&gt;」としなければなりません。&lt;/p&gt;&lt;/li&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-O4QlO7ccdO8/TuizKjcS7_I/AAAAAAAAAoE/hTyww9tKaO4/s1600/db1.png" imageanchor="1" style=""&gt;&lt;img border="0" height="106" width="320" src="http://3.bp.blogspot.com/-O4QlO7ccdO8/TuizKjcS7_I/AAAAAAAAAoE/hTyww9tKaO4/s320/db1.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;そうしていない場合はDropboxSDKが次のようなエラーを報告するかもしれません。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;2011-12-02 01:38:03.935 DBRoulette[8405:207] [ERROR] DropboxSDK: unable to link; app isn't registered for correct URL scheme (db-xxxxxxxxxxxxxxx)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;なお、カスタムURLスキーム自体については「&lt;a href="http://safx-dev.blogspot.com/2010/10/iosurl.html"&gt;iOSで独自カスタムURLスキームを設定する方法について&lt;/a&gt;」を参照してください。&lt;/p&gt;
&lt;li&gt;コンパイルして実行し、Link DropboxをタップするとSafariが起動します。アクセスを許可すると、以前の同様にPhotosフォルダ内にある画像ファイルをランダムに表示します。&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-RvA9TdtezXs/TuizK1D-6EI/AAAAAAAAAoQ/3E3kCC5oDDA/s1600/db2.png" imageanchor="1" style=""&gt;&lt;img border="0" height="320" width="214" src="http://4.bp.blogspot.com/-RvA9TdtezXs/TuizK1D-6EI/AAAAAAAAAoQ/3E3kCC5oDDA/s320/db2.png" /&gt;&lt;/a&gt;
&lt;a href="http://1.bp.blogspot.com/-7SXgCw28IEw/TuizLKcC18I/AAAAAAAAAoc/x-5PgvOmCZA/s1600/db3.png" imageanchor="1" style=""&gt;&lt;img border="0" height="320" width="214" src="http://1.bp.blogspot.com/-7SXgCw28IEw/TuizLKcC18I/AAAAAAAAAoc/x-5PgvOmCZA/s320/db3.png" /&gt;&lt;/a&gt;
&lt;a href="http://1.bp.blogspot.com/-y4O1OaPAVl0/TuizLWvZF3I/AAAAAAAAAos/-5XuHT9As94/s1600/db4.png" imageanchor="1" style=""&gt;&lt;img border="0" height="320" width="214" src="http://1.bp.blogspot.com/-y4O1OaPAVl0/TuizLWvZF3I/AAAAAAAAAos/-5XuHT9As94/s320/db4.png" /&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;h3&gt;まとめ&lt;/h3&gt;

&lt;p&gt;Xcode4.2でのDropbox SDK v1のサンプルアプリケーションのコンパイルについて紹介しました。&lt;/p&gt;

&lt;h3&gt;関連項目&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://safx-dev.blogspot.com/2011/10/dropbox-api-v1.html"&gt;さふ開発日記: Dropbox API V1が正式版になりました&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.dropbox.com/developers"&gt;Dropbox - Developers - Simplify your life&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5191809332257264217-2406622711151115127?l=safx-dev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/PClFKVZq-SZZ_7hkV5Jlm949fVc/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/PClFKVZq-SZZ_7hkV5Jlm949fVc/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/PClFKVZq-SZZ_7hkV5Jlm949fVc/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/PClFKVZq-SZZ_7hkV5Jlm949fVc/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/TFCRl/~4/8qLC07wLUpU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://safx-dev.blogspot.com/feeds/2406622711151115127/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://safx-dev.blogspot.com/2011/12/xcode42dropbox-sdk-v1.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/2406622711151115127?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/2406622711151115127?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/TFCRl/~3/8qLC07wLUpU/xcode42dropbox-sdk-v1.html" title="Xcode4.2でのDropbox SDK v1のサンプルアプリケーションのコンパイルについて" /><author><name>safx developer</name><uri>http://www.blogger.com/profile/13931453776402259724</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/-xmu-GKy-rZo/TY10GvG4LYI/AAAAAAAAAgo/2rul0qNef4Q/s220/%255Bsafx%255D%2B-%2B%25E3%2581%2595%25E3%2581%25B5%25E9%2596%258B%25E7%2599%25BA%25E8%2580%2585.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-7SXgCw28IEw/TuizLKcC18I/AAAAAAAAAoc/x-5PgvOmCZA/s72-c/db3.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://safx-dev.blogspot.com/2011/12/xcode42dropbox-sdk-v1.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEUHRnc7eSp7ImA9WhRTEEs.&quot;"><id>tag:blogger.com,1999:blog-5191809332257264217.post-7824521995942837020</id><published>2011-10-24T00:53:00.002+09:00</published><updated>2011-10-31T22:03:57.901+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-31T22:03:57.901+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="iPhone" /><category scheme="http://www.blogger.com/atom/ns#" term="Dropbox SDK" /><title>Dropbox API V1が正式版になりました</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-YfU5rj4NZy0/TqQ3wKZq1FI/AAAAAAAAAnk/dSO4w3BMofg/s1600/Screen%2Bshot%2B2011-10-24%2Bat%2B0.49.34.png" imageanchor="1" style=""&gt;&lt;img border="0" height="161" width="190" src="http://1.bp.blogspot.com/-YfU5rj4NZy0/TqQ3wKZq1FI/AAAAAAAAAnk/dSO4w3BMofg/s320/Screen%2Bshot%2B2011-10-24%2Bat%2B0.49.34.png" /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;10月23日にbetaが取れて正式版のDropbox API V1がアナウンスされましたので、Changelogで述べられている内容を挙げていきます。&lt;/p&gt;

&lt;a name='more'&gt;&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;ARCを用いているプロジェクトでも利用可能なようにframework化した。そのため、importを次のように変更させる必要がある。&lt;/p&gt;
&lt;pre&gt;#import &amp;lt;DropboxSDK/DropboxSDK.h&amp;gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;新しい認証メソッドを利用するようにした。SDKでのログインやアカウント作成はできなくなったのでDBSession#linkを用いる必要がある。これは公式アプリ(インストールされているなら)、もしくはSafariを起動させて、ユーザにアクセス許可設定をさせるようになっている。&lt;/li&gt;
&lt;li&gt;アプリ中に複数ユーザを扱えるようにした。&lt;/li&gt;
&lt;li&gt;DBMetadataにrevフィールドを追加した。revisionは非推奨となった。&lt;/li&gt;
&lt;li&gt;DBRestClient#loadRevisionsForFile:で過去ファイルのリビジョンのリストを取得できるようになった。ファイルの取得にはloadFile:atRev:intoPath:を、復元にはrestoreFile:toRev:を用いる。&lt;/li&gt;
&lt;li&gt;ファイルアップロード方法の更新した。parentRevパラメータがオプションに追加され、アップロード時にサーバ側のバージョンと異なるときはコンフリクトしたと見なして別名のファイルを作成する。DBRestClientDelegateのコールバックにメタデータが追加されており(restClient:uploadedFile:from:metadata:)、コンフリクトした場合はそのファイル名などを確認できる。&lt;/li&gt;
&lt;li&gt;DBRestClientに検索のメソッドsearchPath:forKeyword:を追加した。&lt;/li&gt;
&lt;li&gt;DBRestClientにファイル共有のメソッドloadSharableLinkForFile:を追加した。&lt;/li&gt;
&lt;li&gt;DBRestClientにファイルストリーミングのリンクを作成するメソッドoadStreamableURLForFile:を追加した。&lt;/li&gt;
&lt;li&gt;.pngと.gifのサムネイルダウンロードでは.pngが得られるようにした。&lt;/li&gt;
&lt;li&gt;バグフィックス&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;なお、利用にはiOS SDK 4.2以降、Xcode 3.2.5以降が必要とのことです。beta版から大きく違いはなさそうですが正式バージョンがアナウンスされたので対応アプリも増えていくことでしょう。&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5191809332257264217-7824521995942837020?l=safx-dev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Bf0JSOmpDgZABCAQkdbV9Hf0pqo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Bf0JSOmpDgZABCAQkdbV9Hf0pqo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Bf0JSOmpDgZABCAQkdbV9Hf0pqo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Bf0JSOmpDgZABCAQkdbV9Hf0pqo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/TFCRl/~4/AW77Jfox7gw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://safx-dev.blogspot.com/feeds/7824521995942837020/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://safx-dev.blogspot.com/2011/10/dropbox-api-v1.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/7824521995942837020?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/7824521995942837020?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/TFCRl/~3/AW77Jfox7gw/dropbox-api-v1.html" title="Dropbox API V1が正式版になりました" /><author><name>safx developer</name><uri>http://www.blogger.com/profile/13931453776402259724</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/-xmu-GKy-rZo/TY10GvG4LYI/AAAAAAAAAgo/2rul0qNef4Q/s220/%255Bsafx%255D%2B-%2B%25E3%2581%2595%25E3%2581%25B5%25E9%2596%258B%25E7%2599%25BA%25E8%2580%2585.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-YfU5rj4NZy0/TqQ3wKZq1FI/AAAAAAAAAnk/dSO4w3BMofg/s72-c/Screen%2Bshot%2B2011-10-24%2Bat%2B0.49.34.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://safx-dev.blogspot.com/2011/10/dropbox-api-v1.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkUNRH0-eSp7ImA9WhdVEko.&quot;"><id>tag:blogger.com,1999:blog-5191809332257264217.post-4002647946525195424</id><published>2011-09-17T23:38:00.000+09:00</published><updated>2011-09-17T23:38:15.351+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-17T23:38:15.351+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="iPhone" /><category scheme="http://www.blogger.com/atom/ns#" term="Dropbox SDK" /><category scheme="http://www.blogger.com/atom/ns#" term="Python" /><title>Dropbox API v1 Betaがアナウンスされました</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-FIoBzE_ShjU/TnSwHi5eCFI/AAAAAAAAAnU/9TsTInPf0Q0/s1600/Screen%2Bshot%2B2011-09-17%2Bat%2B23.08.29.png" imageanchor="1" style=""&gt;&lt;img border="0" height="196" width="320" src="http://3.bp.blogspot.com/-FIoBzE_ShjU/TnSwHi5eCFI/AAAAAAAAAnU/9TsTInPf0Q0/s320/Screen%2Bshot%2B2011-09-17%2Bat%2B23.08.29.png" /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;9月15日にDropbox API v1 Betaが&lt;a href="https://www.dropbox.com/developers/announcements/10"&gt;アナウンスされました&lt;/a&gt;。blogで述べられている内容についてiOSに関連のあるおもしろそうなものから順に挙げていきます。&lt;/p&gt;

&lt;a name='more'&gt;&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;新APIになって、ファイルの共有、ストリーミング、ファイル名検索、リビジョンサポートの機能が追加された。&lt;/li&gt;
&lt;li&gt;アップロードオプションが改良されて衝突の解消や不用意な上書きを回避できるようになった。&lt;/li&gt;
&lt;li&gt;セキュリティ機能が改善されて、新しいシングルサインオン認証が追加された。&lt;/li&gt;
&lt;li&gt;ディベロッパサイトを更新した。&lt;/li&gt;
&lt;li&gt;iOS, Android, Python, Ruby, JavaのSDKがアップデートされた。
&lt;/li&gt;
&lt;li&gt;ウェブアプリがサポートされるようになった。&lt;/li&gt;
&lt;li&gt;"app folder"モードのサポートが再び追加された (以前は"sandbox"と呼ばれていた)。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;追加されたメソッドの中でよさそうなものは次の通り。uploadFileについては以前のものは非推奨になっているようです。&lt;/p&gt;
&lt;pre class="brush:cpp"&gt;
/* This will load a file as it existed at a given rev */
- (void)loadFile:(NSString *)path atRev:(NSString *)rev intoPath:(NSString *)destPath;

/* Uploads a file that will be named filename to the given path on the server. sourcePath is the
   full path of the file you want to upload. If you are modifying a file, parentRev represents the
   rev of the file before you modified it as returned from the server. If you are uploading a new
   file set parentRev to nil. */
- (void)uploadFile:(NSString *)filename toPath:(NSString *)path withParentRev:(NSString *)parentRev
    fromPath:(NSString *)sourcePath;

/* Loads a list of up to 10 DBMetadata objects representing past revisions of the file at path */
- (void)loadRevisionsForFile:(NSString *)path;

/* Restores a file at path as it existed at the given rev and returns the metadata of the restored
   file after restoration */
- (void)restoreFile:(NSString *)path toRev:(NSString *)rev;

- (void)searchPath:(NSString*)path forKeyword:(NSString*)keyword;

- (void)loadSharableLinkForFile:(NSString *)path;

- (void)loadStreamableURLForFile:(NSString *)path;
&lt;/pre&gt;

&lt;p&gt;リビジョン関連のメソッドが増えているのでリビジョンの判定や処理が楽になりそうです。まだ試していませんが、ストリーミングも楽にできそうですし全体的に使いやすくなっている印象を受けました。正式版が待ちどおしいですね。&lt;/p&gt;

&lt;h3&gt;関連項目&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.dropbox.com/developers_beta"&gt;Dropbox - Developers - Simplify your life&lt;/a&gt; (Dropboxアカウントが必要)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://forums.dropbox.com/topic.php?id=44600"&gt;(9/14) - Announcing... API v1 Beta! « Dropbox Forums&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5191809332257264217-4002647946525195424?l=safx-dev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/230LvB_ZnRsLVHVtSDT7DI5JZxE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/230LvB_ZnRsLVHVtSDT7DI5JZxE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/230LvB_ZnRsLVHVtSDT7DI5JZxE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/230LvB_ZnRsLVHVtSDT7DI5JZxE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/TFCRl/~4/iLCehG5c668" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://safx-dev.blogspot.com/feeds/4002647946525195424/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://safx-dev.blogspot.com/2011/09/dropbox-api-v1-beta.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/4002647946525195424?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/4002647946525195424?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/TFCRl/~3/iLCehG5c668/dropbox-api-v1-beta.html" title="Dropbox API v1 Betaがアナウンスされました" /><author><name>safx developer</name><uri>http://www.blogger.com/profile/13931453776402259724</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/-xmu-GKy-rZo/TY10GvG4LYI/AAAAAAAAAgo/2rul0qNef4Q/s220/%255Bsafx%255D%2B-%2B%25E3%2581%2595%25E3%2581%25B5%25E9%2596%258B%25E7%2599%25BA%25E8%2580%2585.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-FIoBzE_ShjU/TnSwHi5eCFI/AAAAAAAAAnU/9TsTInPf0Q0/s72-c/Screen%2Bshot%2B2011-09-17%2Bat%2B23.08.29.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://safx-dev.blogspot.com/2011/09/dropbox-api-v1-beta.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUUBRXg6eyp7ImA9WhdWEU4.&quot;"><id>tag:blogger.com,1999:blog-5191809332257264217.post-3121827786161308408</id><published>2011-09-04T18:32:00.001+09:00</published><updated>2011-09-04T19:47:34.613+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-04T19:47:34.613+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="QuickDialog" /><category scheme="http://www.blogger.com/atom/ns#" term="Blocks" /><title>QuickDialogを用いて簡単にダイアログを作成・表示する</title><content type="html">&lt;p&gt;&lt;a href="https://github.com/escoz/QuickDialog"&gt;QuickDialog&lt;/a&gt;はUITableViewを使わないで簡単にダイアログを作成・表示するiOS用のライブラリで、Apacheライセンスで配布されています。&lt;/p&gt;

&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-pwQFuQBqMok/TmNEJnc6IkI/AAAAAAAAAl8/e3YjRwvEc_k/s1600/QuickDialog00.png" imageanchor="1" style=""&gt;&lt;img border="0" height="320" width="298" src="http://2.bp.blogspot.com/-pwQFuQBqMok/TmNEJnc6IkI/AAAAAAAAAl8/e3YjRwvEc_k/s320/QuickDialog00.png" /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;本記事ではQuickDialogの導入と利用の手順を簡単に説明します。なお、自動参照カウント(ARC)を利用しているので利用にはXCode 4.2 betaが必要です。&lt;/p&gt;
&lt;a name='more'&gt;&lt;/a&gt;
&lt;h3&gt;導入&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="http://mac.github.com/"&gt;GitHub for Mac&lt;/a&gt;をインストールします。&lt;/li&gt;

&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-aNekTk9s1Uc/TmNEJ2yo8II/AAAAAAAAAmE/9kCblYWbo-Y/s1600/QuickDialog01.png" imageanchor="1" style=""&gt;&lt;img border="0" height="106" width="320" src="http://1.bp.blogspot.com/-aNekTk9s1Uc/TmNEJ2yo8II/AAAAAAAAAmE/9kCblYWbo-Y/s320/QuickDialog01.png" /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;li&gt;GitHubの&lt;a href="https://github.com/escoz/QuickDialog"&gt;QuickDialog&lt;/a&gt;へ行き、Clone in Macをクリックします。&lt;/li&gt;

&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-0sVGkwd4jWQ/TmNEKFdovAI/AAAAAAAAAmM/W4xhA4DlVpA/s1600/QuickDialog02.png" imageanchor="1" style=""&gt;&lt;img border="0" height="79" width="320" src="http://2.bp.blogspot.com/-0sVGkwd4jWQ/TmNEKFdovAI/AAAAAAAAAmM/W4xhA4DlVpA/s320/QuickDialog02.png" /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;li&gt;GitHub for Macが起動して必要な設定を埋めてくれているので[OK]をクリック。&lt;/li&gt;

&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-iUWtCs-017k/TmNEKC32egI/AAAAAAAAAmU/lzz4ZDPMlCk/s1600/QuickDialog03.png" imageanchor="1" style=""&gt;&lt;img border="0" height="293" width="320" src="http://4.bp.blogspot.com/-iUWtCs-017k/TmNEKC32egI/AAAAAAAAAmU/lzz4ZDPMlCk/s320/QuickDialog03.png" /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;li&gt;プロジェクトを作成します。&lt;/li&gt;
&lt;li&gt;プロジェクトに先ほどCloneしたQuickDialog内のフォルダquickdialogを追加します。&lt;/li&gt;
&lt;li&gt;プロジェクトの[Build Phase]→[Link Binary with Libraries]にMapKit.Frameworkを追加します。&lt;/li&gt;
&lt;li&gt;sample/quickdialogexample-Prefix.pchを参考に、Foobar-Prefix.pchに次のようなimportを追加します。
&lt;pre class="brush:cpp"&gt;
#import "QuickDialogController.h"
#import "QuickDialogController+Loading.h"
#import "QuickDialogStyleProvider.h"
#import "QLabelElement.h"
#import "QBadgeElement.h"
#import "QBooleanElement.h"
#import "QButtonElement.h"
#import "QDateTimeInlineElement.h"
#import "QFloatElement.h"
#import "QMapElement.h"
#import "QRadioElement.h"
#import "QRadioItemElement.h"
#import "QTextElement.h"
#import "QWebElement.h"
#import "QDecimalElement.h"
#import "QSortingSection.h"
#import "QDateTimeElement.h"
&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;利用法&lt;/h3&gt;

&lt;p&gt;次のように、QRootElementにいろいろ要素を追加していき、最後にこれを用いてQuickDialogControllerを作成します。&lt;/p&gt;

&lt;pre class="brush:cpp"&gt;QRootElement* root = [[QRootElement alloc] init];
root.grouped = YES;
root.title = @"ダイアログサンプル";

QSection* detailsSection = [[QSection alloc] initWithTitle:@"いろいろサンプル"];     
[root addSection:detailsSection];

QFloatElement* q1 = [[QFloatElement alloc] initWithTitle:@"スライダー" value:1];
[detailsSection addElement:q1];

QDecimalElement* q2 = [[QDecimalElement alloc] initWithTitle:@"10進数" value:0.25];  
[detailsSection addElement:q2];

QBadgeElement* q3 = [[QBadgeElement alloc] initWithTitle:@"バッジ付き" Value:@"Foo"];
q3.badge = @"1";
[detailsSection addElement:q3];

QBooleanElement* q4 = [[QBooleanElement alloc] initWithTitle:@"Boolean" BoolValue:TRUE];
[detailsSection addElement:q4];

QDateTimeInlineElement* q5 = [[QDateTimeInlineElement alloc] initWithTitle:@"時間" date:[NSDate date]];
[detailsSection addElement:q5];

QuickDialogController* qcont = [[QuickDialogController alloc] initWithRoot:root];
UINavigationController* navigation = [[UINavigationController alloc] initWithRootViewController:qcont];
[self presentModalViewController:navigation animated:YES];
&lt;/pre&gt;

&lt;p&gt;これで次のようなビューが作成されます。&lt;/p&gt;

&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-r1BwWSCXMC8/TmNEd-82ShI/AAAAAAAAAmc/UV6DT4uwj2Q/s1600/QuickDialog11.png" imageanchor="1" style=""&gt;&lt;img border="0" height="320" width="214" src="http://3.bp.blogspot.com/-r1BwWSCXMC8/TmNEd-82ShI/AAAAAAAAAmc/UV6DT4uwj2Q/s320/QuickDialog11.png" /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;Blocksを用いてビューが消える時のコールバックを設定することもできます。&lt;/p&gt;

&lt;pre class="brush:cpp"&gt;q1.key = @"slider-value";
q2.key = @"decimal-value";
q3.key = @"badge-value";
q4.key = @"bool-value";
q5.key = @"time-value";

qcont.willDisappearCallback = ^() {
    NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
    [root fetchValueIntoObject:dict];

    NSString *msg = @"Values:";
    for (NSString *aKey in dict){
        msg = [msg stringByAppendingFormat:@"\n- %@: %@", aKey, [dict valueForKey:aKey]];
    }
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Hello"
                                                message:msg delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [alert show];
};
&lt;/pre&gt;

&lt;p&gt;これで、ビューが消えるときに次のようなアラートが表示されます。&lt;/p&gt;

&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-RMQOs8ysbQ8/TmNEeAMSYbI/AAAAAAAAAmk/vuWpY_fb9pw/s1600/QuickDialog12.png" imageanchor="1" style=""&gt;&lt;img border="0" height="239" width="284" src="http://4.bp.blogspot.com/-RMQOs8ysbQ8/TmNEeAMSYbI/AAAAAAAAAmk/vuWpY_fb9pw/s320/QuickDialog12.png" /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;テーブルのセルには時間やマップを扱えるものがあります。QuickDialog内にサンプルがありますので試してみるとよいでしょう。&lt;/p&gt;

&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-2J5M3Kqk_co/TmNEeFRilcI/AAAAAAAAAms/dEH4g8V9IVA/s1600/QuickDialog13.png" imageanchor="1" style=""&gt;&lt;img border="0" height="320" width="214" src="http://4.bp.blogspot.com/-2J5M3Kqk_co/TmNEeFRilcI/AAAAAAAAAms/dEH4g8V9IVA/s320/QuickDialog13.png" /&gt;&lt;/a&gt;
&lt;a href="http://2.bp.blogspot.com/-VcKUtFh-nfA/TmNEeT_jNXI/AAAAAAAAAm0/qdg29kHJm1c/s1600/QuickDialog14.png" imageanchor="1" style=""&gt;&lt;img border="0" height="320" width="214" src="http://2.bp.blogspot.com/-VcKUtFh-nfA/TmNEeT_jNXI/AAAAAAAAAm0/qdg29kHJm1c/s320/QuickDialog14.png" /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;h3&gt;まとめ&lt;/h3&gt;

&lt;p&gt;QuickDialogの導入と利用について簡単に説明しました。&lt;/p&gt;

&lt;h3&gt;関連項目&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/escoz/QuickDialog"&gt;escoz/QuickDialog - GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://mac.github.com/"&gt;GitHub for Mac&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5191809332257264217-3121827786161308408?l=safx-dev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/QtyJjwLL7TG3MKg0_9v2b2otH6M/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QtyJjwLL7TG3MKg0_9v2b2otH6M/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/QtyJjwLL7TG3MKg0_9v2b2otH6M/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QtyJjwLL7TG3MKg0_9v2b2otH6M/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/TFCRl/~4/PFWwO5Baf60" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://safx-dev.blogspot.com/feeds/3121827786161308408/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://safx-dev.blogspot.com/2011/09/quickdialog.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/3121827786161308408?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/3121827786161308408?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/TFCRl/~3/PFWwO5Baf60/quickdialog.html" title="QuickDialogを用いて簡単にダイアログを作成・表示する" /><author><name>safx developer</name><uri>http://www.blogger.com/profile/13931453776402259724</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/-xmu-GKy-rZo/TY10GvG4LYI/AAAAAAAAAgo/2rul0qNef4Q/s220/%255Bsafx%255D%2B-%2B%25E3%2581%2595%25E3%2581%25B5%25E9%2596%258B%25E7%2599%25BA%25E8%2580%2585.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-pwQFuQBqMok/TmNEJnc6IkI/AAAAAAAAAl8/e3YjRwvEc_k/s72-c/QuickDialog00.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://safx-dev.blogspot.com/2011/09/quickdialog.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0MHRHw-eip7ImA9WhRVEUQ.&quot;"><id>tag:blogger.com,1999:blog-5191809332257264217.post-3764944297345483232</id><published>2011-07-02T20:14:00.003+09:00</published><updated>2012-01-10T21:43:55.252+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-10T21:43:55.252+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="統計情報" /><title>2011年上半期の人気記事一覧と統計情報</title><content type="html">&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-CsbB8dtkQ2A/Tg8CL_Bl4RI/AAAAAAAAAlg/oAfuw4-53bE/s1600/P5039943.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 320px;" src="http://2.bp.blogspot.com/-CsbB8dtkQ2A/Tg8CL_Bl4RI/AAAAAAAAAlg/oAfuw4-53bE/s320/P5039943.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5624716864528965906" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2011年上半期で本ブログの記事の中で人気のあったページや統計情報をまとめてみました。これらはGoogle AnalyticsとBloggerの統計タブによる情報に基づいています。&lt;/p&gt;

&lt;a name='more'&gt;&lt;/a&gt;

&lt;p&gt;2011年上半期の間でアクセス数の多かったページは次の通りです。他のアプリケーションやサービスとの連携記事が人気があるようです。&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;img class="none" src="http://lh3.ggpht.com/_XbtP-rrPvTg/TKWBAQRcnvI/AAAAAAAAALc/L1B7aPJyu1Q/s72-c/Screen%20shot%202010-09-30%20at%2019.56.57.png"/&gt;&lt;a href="http://safx-dev.blogspot.com/2010/10/iosurl.html"&gt;iOSで独自カスタムURLスキームを設定する方法について&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;img class="none" src="http://lh5.ggpht.com/_XbtP-rrPvTg/TKRHn5ilGHI/AAAAAAAAAKg/vovcA7_ZrlQ/s72-c/urlscheme_sample.png"/&gt;&lt;a href="http://safx-dev.blogspot.com/2010/09/iosurl.html"&gt;iOSでカスタムURLスキームを利用してアプリケーションを起動する方法について&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;img class="none" src="http://lh6.ggpht.com/_XbtP-rrPvTg/TLhyt0cu3II/AAAAAAAAAOo/InCRLssARKw/s72-c/viewmanagement.png"/&gt;&lt;a href="http://safx-dev.blogspot.com/2010/10/viewcontroller.html"&gt;ViewControllerにおけるビュー管理サイクルとメモリ警告シミュレーションによるアンロード処理について&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;img class="none" src="http://lh6.ggpht.com/_XbtP-rrPvTg/TOUO0P38ovI/AAAAAAAAASA/RhyOnZFNhf4/s72-c/q1a.png"/&gt;&lt;a href="http://safx-dev.blogspot.com/2010/11/uidocumentinteractioncontroller.html"&gt;UIDocumentInteractionControllerを用いて別アプリケーションを開くメニューを表示する方法について&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;img class="none" src="http://lh6.ggpht.com/_XbtP-rrPvTg/TSSAukb_jYI/AAAAAAAAAWQ/XahvWXWhUpA/s72-c/xc02.png"/&gt;&lt;a href="http://safx-dev.blogspot.com/2011/01/xcode-325ios-40-sdk.html"&gt;Xcode 3.2.5にiOS 4.0 SDKを導入する方法について&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;img class="none" src="http://lh6.ggpht.com/_XbtP-rrPvTg/TOfrvv9IdsI/AAAAAAAAASY/3GquGg_Kd5A/s72-c/Screen%20shot%202010-11-20%20at%2022.04.13.png" /&gt;&lt;a href="http://safx-dev.blogspot.com/2010/11/ios_21.html"&gt;iOSアプリケーションを特定のファイル形式に対応させる方法について&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;img class="none" src="http://lh6.ggpht.com/_XbtP-rrPvTg/TKSdEyHWDEI/AAAAAAAAAK0/mhdVvQf2e0I/s72-c/ios_state.png" /&gt;&lt;a href="http://safx-dev.blogspot.com/2010/09/ios-4.html"&gt;iOS 4のマルチタスク処理における状態遷移について&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;img class="none" src="http://lh3.ggpht.com/_XbtP-rrPvTg/TNkL2CVt0vI/AAAAAAAAARM/86J2qHI5jIU/s72-c/PA036663.jpg" /&gt;&lt;a href="http://safx-dev.blogspot.com/2010/11/nsurlconnectionurl.html"&gt;NSURLConnectionを用いたURLローディングシステムによる通信&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;img class="none" src="http://lh4.ggpht.com/_XbtP-rrPvTg/THvcSWbrhqI/AAAAAAAAAFI/bz9ZDvB6juI/s72-c/dbox01.png" /&gt;&lt;a href="http://safx-dev.blogspot.com/2010/08/dropbox-sdk-for-ios.html"&gt;Dropbox SDK for iOSのためのディベロッパキーの取得方法とサンプルアプリケーションのコンパイルについて&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;img class="none" src="http://lh4.ggpht.com/_XbtP-rrPvTg/TM_s41Od5OI/AAAAAAAAAQ4/qdK-6UW5FhQ/s72-c/icon2.png" /&gt;&lt;a href="http://safx-dev.blogspot.com/2010/11/ios.html"&gt;iOSアプケーションにバンドルする画像リソースについて&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;ページビュー数の月ごとの遷移は次のようになりました。今年に入ってから徐々にアクセスが増えています。&lt;/p&gt;

&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-eZLisN-zNzA/Tg79wT2tFRI/AAAAAAAAAlE/M3IbkynC73M/s1600/stat001.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 96px;" src="http://3.bp.blogspot.com/-eZLisN-zNzA/Tg79wT2tFRI/AAAAAAAAAlE/M3IbkynC73M/s320/stat001.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5624711991037596946" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ブログ開設から全期間内でのページビューのブラウザ別の割合は次のようになりました。1%未満のものにはOpera, OneRiot, RockMeltなどがありました。&lt;/p&gt;

&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-QxSFxlEmQjE/Tg79wtyqejI/AAAAAAAAAlM/Zc4fSYEtSIw/s1600/stat002.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 237px; height: 103px;" src="http://1.bp.blogspot.com/-QxSFxlEmQjE/Tg79wtyqejI/AAAAAAAAAlM/Zc4fSYEtSIw/s320/stat002.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5624711997999970866" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;table class="mytable"&gt;
&lt;tr&gt;&lt;th&gt;ブラウザ&lt;/th&gt;&lt;th&gt;割合&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Safari&lt;/td&gt;&lt;td&gt;26%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Firefox&lt;/td&gt;&lt;td&gt;24%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Chrome&lt;/td&gt;&lt;td&gt;21%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Apple-PubSub&lt;/td&gt;&lt;td&gt;10%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Internet Explorer&lt;/td&gt;&lt;td&gt;9%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Google Desktop&lt;/td&gt;&lt;td&gt;4%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Mobile&lt;/td&gt;&lt;td&gt;2%&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;ブログ開設から全期間内でのページビューのOS別の割合は次の通りです。やはりMacが多いです。なお、1%未満のものにはLinux, iPod, Androidなどがありました。&lt;/p&gt;

&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-2nwJPldQUaE/Tg79ww2gEzI/AAAAAAAAAlU/FRyrPh8zkD0/s1600/stat003.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 234px; height: 116px;" src="http://4.bp.blogspot.com/-2nwJPldQUaE/Tg79ww2gEzI/AAAAAAAAAlU/FRyrPh8zkD0/s320/stat003.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5624711998821372722" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;table class="mytable"&gt;
&lt;tr&gt;&lt;th&gt;OS&lt;/th&gt;&lt;th&gt;割合&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Mac&lt;/td&gt;&lt;td&gt;55%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Windows&lt;/td&gt;&lt;td&gt;36%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;iPhone&lt;/td&gt;&lt;td&gt;4%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Other Unix&lt;/td&gt;&lt;td&gt;1%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;iPad&lt;/td&gt;&lt;td&gt;1%&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;今後は、もう少し更新頻度を上げたいと思っておりますので文章的に小さめの記事が増えるかもしれませんが、引き続きプログラム関連の記事をメインにしていくつもりです。&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5191809332257264217-3764944297345483232?l=safx-dev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/QBJqNhgsGSCkD7J9fchI9kHrx-Y/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QBJqNhgsGSCkD7J9fchI9kHrx-Y/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/QBJqNhgsGSCkD7J9fchI9kHrx-Y/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QBJqNhgsGSCkD7J9fchI9kHrx-Y/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/TFCRl/~4/eDiDOp5mrsA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://safx-dev.blogspot.com/feeds/3764944297345483232/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://safx-dev.blogspot.com/2011/07/2011.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/3764944297345483232?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/3764944297345483232?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/TFCRl/~3/eDiDOp5mrsA/2011.html" title="2011年上半期の人気記事一覧と統計情報" /><author><name>safx developer</name><uri>http://www.blogger.com/profile/13931453776402259724</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/-xmu-GKy-rZo/TY10GvG4LYI/AAAAAAAAAgo/2rul0qNef4Q/s220/%255Bsafx%255D%2B-%2B%25E3%2581%2595%25E3%2581%25B5%25E9%2596%258B%25E7%2599%25BA%25E8%2580%2585.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-CsbB8dtkQ2A/Tg8CL_Bl4RI/AAAAAAAAAlg/oAfuw4-53bE/s72-c/P5039943.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://safx-dev.blogspot.com/2011/07/2011.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEcEQ3syeip7ImA9WhdWEEg.&quot;"><id>tag:blogger.com,1999:blog-5191809332257264217.post-5836405020194702133</id><published>2011-06-26T22:25:00.006+09:00</published><updated>2011-09-03T21:13:22.592+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-03T21:13:22.592+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Shiboken" /><category scheme="http://www.blogger.com/atom/ns#" term="PySide" /><category scheme="http://www.blogger.com/atom/ns#" term="Qt" /><category scheme="http://www.blogger.com/atom/ns#" term="バインディング" /><category scheme="http://www.blogger.com/atom/ns#" term="C++" /><category scheme="http://www.blogger.com/atom/ns#" term="Python" /><title>Shibokenを用いたCPython用バインディングの生成について</title><content type="html">&lt;p&gt;ShibokenはC++ライブラリからCPython用バインディングを生成するPySide付属のユーティリティです。本来はPySideプロジェクトが、QtのCPython用バインディングを作るためのツールですが他のC++ライブラリにも適用できます。&lt;/p&gt;&lt;p&gt;そこで、本記事ではShibokenを用いて既存のC++ライブラリのバインディングを作成し、それを用いるまでの手順を簡単に説明します。なお、環境はMac OS XでApple公式のPythonを用いています。&lt;/p&gt;&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-F1P6jPZne24/Tgc1wXE22XI/AAAAAAAAAk4/8jl2OZlKk4k/s1600/shiboken.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 480px; height: 225px;" src="http://1.bp.blogspot.com/-F1P6jPZne24/Tgc1wXE22XI/AAAAAAAAAk4/8jl2OZlKk4k/s480/shiboken.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5622521764739733874" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;a name='more'&gt;&lt;/a&gt;  &lt;h4&gt;Shibokenの概要&lt;/h4&gt;&lt;p&gt;Shibokenは次の3つから構成されています。&lt;/p&gt;&lt;ul&gt;&lt;li&gt;API ExtractorはPySideで使われているバインディング生成ライブラリです。ライブラリヘッダを解析した情報と型情報が書かれたXMLファイルの情報を統合して、選択した言語のバインディングを生成します。&lt;/li&gt;
&lt;li&gt;Generator RunnerはAPI Extractorのコマンドラインフロントエンドです。&lt;/li&gt;
&lt;li&gt;ShibokenはC++ライブラリからCPython用バインディングを生成するGenerator Runnerプラグインです。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;また、生成の過程を表したものが上の図です。設定ファイルや型情報ファイルを与えると、ヘッダファイル群を読み込んでPython用のバインディングが作られます。後はこれをコンパイルしてやればPythonで利用できるようになります。&lt;/p&gt;&lt;h4&gt;libraw-liteのPythonバインディング作成&lt;/h4&gt;&lt;p&gt;&lt;a href="http://www.libraw.org/libraw-lite"&gt;LibRaw-Lite&lt;/a&gt;はデジタルカメラのRawファイルを扱うためのC++ライブラリです。今回はこのライブラリをPythonで使えるようにします。&lt;/p&gt;&lt;p&gt;まずはライブラリを解凍して、コンパイルします。&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&amp;gt; make
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;次に、libraw.h内のLibRaw::add&lt;em&gt;masked&lt;/em&gt;borders&lt;em&gt;to&lt;/em&gt;bitmap()はヘッダには宣言されていますが、定義が存在しないために削除します。 そうしなければ、pythonでimportしたときに次のようなエラーになります。&lt;/p&gt;&lt;pre&gt;&lt;code&gt;ImportError: dlopen(./libraw.so, 2): Symbol not found: __ZN6LibRaw28add_masked_borders_to_bitmapEv
  Referenced from: /Users/foobar/src/LibRaw-Lite-0.7.2/python/libraw/libraw.so
  Expected in: flat namespace
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;そして、shibokenがライブラリのヘッダファイルを簡単に取り込めるようにするため、必要なヘッダをまとめたファイルを作成します。&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&amp;gt; ls libraw/*.h | awk '{printf("#include \"%s\"\n", $1)}' &amp;gt; shiboken.h
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;続いて、型情報を記述するためのファイルshiboken_typesystem.xmlを用意します。 これは次のようなファイルになっており、typesystemのpackageでは出力時のpythonのパッケージ名をlibrawを指定しています。また、primitive-typeは基本型を指定し、object-typeはC++の型をターゲット言語(ここではPython)にマッピングさせるようにしています。&lt;/p&gt;&lt;pre class="brush:bash"&gt;&amp;gt; cat shiboken_typesystem.xml
&amp;lt;?xml version="1.0"?&amp;gt;
&amp;lt;typesystem package="libraw"&amp;gt;
  &amp;lt;primitive-type name="char"/&amp;gt;
  &amp;lt;primitive-type name="int"/&amp;gt;
  &amp;lt;primitive-type name="float"/&amp;gt;
  &amp;lt;primitive-type name="double"/&amp;gt;
  &amp;lt;primitive-type name="unsigned" /&amp;gt;
  &amp;lt;primitive-type name="unsigned int" /&amp;gt;
  &amp;lt;primitive-type name="size_t" /&amp;gt;
  &amp;lt;object-type name="LibRaw" /&amp;gt;
&amp;lt;/typesystem&amp;gt;
&lt;/pre&gt;&lt;p&gt;shiboken_binding.txtはshibokenのコマンドラインオプションを指定するファイルです。先の2ファイルを指定しています。&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&amp;gt; cat shiboken_binding.txt
[generator-project]
header-file = shiboken.h
typesystem-file = shiboken_typesystem.xml
output-directory = python
generator-set = /usr/local/lib/generatorrunner/shiboken_generator.dylib
enable-parent-ctor-heuristic
use-isnull-as-nb_nonzero
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;これでとりあえずバインディングを生成することができます。わからない型を含む関数などは無視されます。&lt;/p&gt;&lt;pre class="brush:cpp"&gt;&amp;gt; shiboken --project-file=shiboken_binding.txt
(中略)
Resolving typedefs...                        [WARNING]
Fixing class inheritance...                  [WARNING]
    skipping function 'LibRaw::gamma_lut', unmatched parameter type 'ushort[0x10000]'
    skipping function 'LibRaw::jpeg_thumb', unmatched parameter type 'FILE*'
    skipping function 'LibRaw::write_ppm_tiff', unmatched parameter type 'FILE*'
    skipping function 'LibRaw::dcraw_make_mem_thumb', unmatched return type 'libraw_processed_image_t*'
(中略)
Detecting inconsistencies in class model...  [OK]
Detecting inconsistencies in typesystem...   [OK]

Done, 29 warnings (0 known issues)
(後略)

&amp;gt; cd python/libraw
&amp;gt; ls   
libraw_abstract_datastream_wrapper.cpp    libraw_output_params_t_wrapper.h
libraw_abstract_datastream_wrapper.h    libraw_processed_image_t_wrapper.cpp
libraw_data_t_wrapper.cpp        libraw_processed_image_t_wrapper.h
libraw_data_t_wrapper.h            libraw_python.h
libraw_module_wrapper.cpp        libraw_wrapper.cpp
libraw_output_params_t_wrapper.cpp    libraw_wrapper.h
&lt;/pre&gt;&lt;p&gt;この出力されたソースを用いてPython拡張のための共有オブジェクトを作成します。 &lt;/p&gt;&lt;pre class="brush:cpp"&gt;&amp;gt; g++ -fPIC -I/System/Library/Frameworks/Python.framework/Headers \
    -I/usr/local/include/shiboken -I../../libraw -bundle \
    -o libraw.so *.cpp -undefined dynamic_lookup \
    /usr/local/lib/libshiboken-python2.7.1.0.2.dylib ../../lib/libraw-lite.a
&lt;/pre&gt;&lt;p&gt;これで、Libraw-Liteの一部の機能は利用できるようになります。次の例ではRawファイルを読み込んでその中に含まれるサムネイルを取り出しています。&lt;/p&gt;&lt;pre class="brush:cpp"&gt;&amp;gt; file P5039940.ORF
P5039940.ORF: data
&amp;gt; python
Python 2.6.6 (r266:84292, Jan 22 2011, 22:32:56) 
[GCC 4.2.1 (Apple Inc. build 5664)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
&amp;gt;&amp;gt;&amp;gt; import libraw
&amp;gt;&amp;gt;&amp;gt; dir(libraw)
['LibRaw', '_Cpp_Api', '__doc__', '__file__', '__name__', '__package__']
&amp;gt;&amp;gt;&amp;gt; r=libraw.LibRaw()
&amp;gt;&amp;gt;&amp;gt; dir(r)
['FC', '__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', 
'__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', 
'__subclasshook__', 'adjust_sizes_info_only', 'cameraCount', 'cameraList', 'dcraw_document_mode_processing', 
'dcraw_ppm_tiff_writer', 'dcraw_process', 'dcraw_thumb_writer', 'fc', 'open_buffer', 'open_file', 
'recycle', 'strerror', 'unpack', 'unpack_function_name', 'unpack_thumb', 'verbose', 'version', 'versionNumber']
&amp;gt;&amp;gt;&amp;gt; r.version()
'0.7.2-Release(Lite)'
&amp;gt;&amp;gt;&amp;gt; r.open_file('P5039940.ORF')
0
&amp;gt;&amp;gt;&amp;gt; r.unpack_thumb()
0
&amp;gt;&amp;gt;&amp;gt; r.dcraw_thumb_writer('thumb.jpg')
0
&amp;gt;&amp;gt;&amp;gt; exit()
&amp;gt; file thumb.jpg 
thumb.jpg:    JPEG image data, EXIF standard
&lt;/pre&gt;&lt;p&gt;実際には、このままでは実行すると落ちてしまう (LibRaw.cameraListなど) 場合も多く、修正が必要です。&lt;/p&gt;&lt;p&gt;ただし、Shibokenでは、型システムファイル(shiboken_typesystem.xml)にそれらのソースの修正を書くことができるため、メンテナンス性も高くなっています。&lt;/p&gt;&lt;p&gt;なお、コード修正の方法については&lt;a href="http://www.pyside.org/docs/shiboken/"&gt;Shibokenのマニュアル&lt;/a&gt;やShibokenソース内にあるサンプルファイルなどを参照してください。&lt;/p&gt;&lt;h4&gt;まとめ&lt;/h4&gt;&lt;p&gt;Shibokenを用いて既存のC++ライブラリのバインディングを作成して利用する方法を説明しました。&lt;/p&gt;&lt;h4&gt;関連情報&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://developer.qt.nokia.com/wiki/PySideDocumentation/"&gt;PySide Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.pyside.org/docs/apiextractor/"&gt;API Extractor — Overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.pyside.org/docs/generatorrunner/"&gt;GeneratorRunner — Overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.pyside.org/docs/shiboken/"&gt;Shiboken — Overview&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5191809332257264217-5836405020194702133?l=safx-dev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Zj3JcV_xhEqHk1I9U4Wg72w-qbM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Zj3JcV_xhEqHk1I9U4Wg72w-qbM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Zj3JcV_xhEqHk1I9U4Wg72w-qbM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Zj3JcV_xhEqHk1I9U4Wg72w-qbM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/TFCRl/~4/IjnyXBv61lw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://safx-dev.blogspot.com/feeds/5836405020194702133/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://safx-dev.blogspot.com/2011/06/shibokencpython.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/5836405020194702133?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/5836405020194702133?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/TFCRl/~3/IjnyXBv61lw/shibokencpython.html" title="Shibokenを用いたCPython用バインディングの生成について" /><author><name>safx developer</name><uri>http://www.blogger.com/profile/13931453776402259724</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/-xmu-GKy-rZo/TY10GvG4LYI/AAAAAAAAAgo/2rul0qNef4Q/s220/%255Bsafx%255D%2B-%2B%25E3%2581%2595%25E3%2581%25B5%25E9%2596%258B%25E7%2599%25BA%25E8%2580%2585.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-F1P6jPZne24/Tgc1wXE22XI/AAAAAAAAAk4/8jl2OZlKk4k/s72-c/shiboken.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://safx-dev.blogspot.com/2011/06/shibokencpython.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0QFRXk6eCp7ImA9WhdWEEg.&quot;"><id>tag:blogger.com,1999:blog-5191809332257264217.post-5024868248966858260</id><published>2011-05-22T15:48:00.007+09:00</published><updated>2011-09-03T21:01:54.710+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-03T21:01:54.710+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ライブラリ" /><category scheme="http://www.blogger.com/atom/ns#" term="iPhone" /><category scheme="http://www.blogger.com/atom/ns#" term="Cinder" /><title>CinderによるiPhoneアプリケーションの作成について</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-5JrnnFqYeok/Tdi4Qp5EzLI/AAAAAAAAAkE/zVnjWCdUnqk/s1600/cinder2.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 167px; height: 320px;" src="http://1.bp.blogspot.com/-5JrnnFqYeok/Tdi4Qp5EzLI/AAAAAAAAAkE/zVnjWCdUnqk/s320/cinder2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5609435932152614066" /&gt;&lt;/a&gt;  &lt;p&gt;Cinderは&lt;a href="http://www.barbariangroup.com/"&gt;The Barbarian Group&lt;/a&gt;が開発しているC++ライブラリで、&lt;a href="http://processing.org/"&gt;Processing.org&lt;/a&gt;のように画像、音声、動画、ネットワークなどを手軽に扱うことができます。CinderはMac OS X, Windows, iPad, iPhoneをサポートしており、修正BSDライセンスによって提供されています。&lt;/p&gt;&lt;p&gt;そこで、本記事ではCinderのiPhone向けのアプリケーションを作成する手順について簡単に説明します。環境はXcode 3.2.5, iOS SDK 4.2, Cinder 0.8.2です。&lt;/p&gt;&lt;a name='more'&gt;&lt;/a&gt;  &lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-zaQL2OGb9z4/Tdi4Ruuv3KI/AAAAAAAAAkU/b599Z9eqn-Y/s1600/Screen%2Bshot%2B2011-05-22%2Bat%2B2.36.42.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 82px; height: 91px;" src="http://4.bp.blogspot.com/-zaQL2OGb9z4/Tdi4Ruuv3KI/AAAAAAAAAkU/b599Z9eqn-Y/s320/Screen%2Bshot%2B2011-05-22%2Bat%2B2.36.42.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5609435950631345314" /&gt;&lt;/a&gt; &lt;h4&gt;プロジェクトの作成と実行&lt;/h4&gt;&lt;p&gt;&lt;a href="http://libcinder.org/"&gt;Cinder&lt;/a&gt;の&lt;a href="http://libcinder.org/download/"&gt;Downloadページ&lt;/a&gt;でCinder for Mac OS XをクリックしてZipファイルをダウンロードし、そのファイルを解凍すればよいです。&lt;/p&gt;&lt;p&gt;ダウンロードしたファイル内にコンパイル済みのライブラリファイルが含まれているのでコンパイルする必要はありません。&lt;/p&gt;&lt;h4&gt;プロジェクトの作成と実行&lt;/h4&gt;&lt;p&gt;次の手順でCinderのXcodeプロジェクトを作成します。&lt;/p&gt;&lt;ol&gt;&lt;li&gt;toolsにあるTinderBoxを実行する。&lt;/li&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-KqUmoPABlFc/Tdi3ZR6M96I/AAAAAAAAAjQ/baq_E2ANi5c/s1600/tinderbox0.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 188px;" src="http://4.bp.blogspot.com/-KqUmoPABlFc/Tdi3ZR6M96I/AAAAAAAAAjQ/baq_E2ANi5c/s320/tinderbox0.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5609434980822087586" /&gt;&lt;/a&gt;
&lt;li&gt;Cinderのトップレベルディレクトリを選択して[Open]をクリックする。&lt;/li&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-KV4H03Qh8KM/Tdi3ZRzP-uI/AAAAAAAAAjY/RTcfBog0IeU/s1600/tinderbox1.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 242px;" src="http://3.bp.blogspot.com/-KV4H03Qh8KM/Tdi3ZRzP-uI/AAAAAAAAAjY/RTcfBog0IeU/s320/tinderbox1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5609434980792924898" /&gt;&lt;/a&gt;
&lt;li&gt;プロジェクトの名前と場所を指定する。ここではプロジェクト名はcinder_sampleにした。&lt;/li&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-XXrsupA3GCc/Tdi3Zg-Y-qI/AAAAAAAAAjg/ZmBHNWtWXbQ/s1600/tinderbox2.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 273px;" src="http://1.bp.blogspot.com/-XXrsupA3GCc/Tdi3Zg-Y-qI/AAAAAAAAAjg/ZmBHNWtWXbQ/s320/tinderbox2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5609434984866183842" /&gt;&lt;/a&gt;
&lt;li&gt;[Target]を[Cocoa Touch]にして[Create]をクリックする。&lt;/li&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-oZiwUzQHY5Q/Tdi3Z1ojlFI/AAAAAAAAAjo/2DZgge0wVDE/s1600/tinderbox3.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 273px;" src="http://1.bp.blogspot.com/-oZiwUzQHY5Q/Tdi3Z1ojlFI/AAAAAAAAAjo/2DZgge0wVDE/s320/tinderbox3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5609434990411748434" /&gt;&lt;/a&gt;
&lt;li&gt;Finderが開くのでディレクトリxcodeにあるxcodeのプロジェクトを開く。&lt;/li&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-q8DASgV3vsc/Tdi3aZaAJYI/AAAAAAAAAjw/WcXu8GG5x7M/s1600/tinderbox4.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 259px;" src="http://4.bp.blogspot.com/-q8DASgV3vsc/Tdi3aZaAJYI/AAAAAAAAAjw/WcXu8GG5x7M/s320/tinderbox4.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5609435000014382466" /&gt;&lt;/a&gt;
&lt;li&gt;(必要に応じて) プロジェクトの設定を変更する。手元の環境では、TinderBoxによってBase SDKの指定がiOS 4.1となっているプロジェクトが生成されましたが、Xcode内にはiOS 4.0とiOS 4.2のSDKしか入っていないためBase SDKをiOS 4.2に変更しました。&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;これで、[Build and Run]を行うと、シミュレータが起動して次のような立方体が回転するプログラムが実行されます。&lt;/p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-nmP3QWna67s/Tdi4Qdu6VqI/AAAAAAAAAj8/ThhLzkq9wRg/s1600/cinder1.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 166px; height: 320px;" src="http://2.bp.blogspot.com/-nmP3QWna67s/Tdi4Qdu6VqI/AAAAAAAAAj8/ThhLzkq9wRg/s320/cinder1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5609435928888759970" /&gt;&lt;/a&gt;  &lt;p&gt;なお、実機に落とすときはInfo.plistのBundle Identifierを適切なものに変更してください。&lt;/p&gt;&lt;h4&gt;Cinderソース概要&lt;/h4&gt;&lt;p&gt;生成されたソースファイルであるiphone_sampleApp.cppを見てみましょう。その中にクラスAppCocoaTouchを継承したクラスcinder_sampleAppが存在します。&lt;/p&gt;&lt;pre class="brush:cpp"&gt;class cinder_sampleApp : public AppCocoaTouch {
  public:
    virtual void    setup();
    virtual void    resize( ResizeEvent event );
    virtual void    update();
    virtual void    draw();
    virtual void    mouseDown( MouseEvent event );

    Matrix44f   mCubeRotation;
    gl::Texture mTex;
    CameraPersp mCam;
};
&lt;/pre&gt;&lt;p&gt;このクラス内には次の3つのメソッドが含まれています。&lt;/p&gt;&lt;ul&gt;&lt;li&gt;setup()はプログラム開始時に一度だけ呼ばれる。ここでプログラム中にある変数の初期化を行う。&lt;/li&gt;
&lt;li&gt;update()はそれらの変数を変更する。&lt;/li&gt;
&lt;li&gt;draw()はウィンドウへの描画を行う。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Cinderのプログラムが起動したら、まずsetupが呼ばれてそれ以後はupdateとdrawが繰り返し呼ばれます。サンプルプログラムでは、setupで立方体のテクスチャを作成し、updateで立方体を回転させ、drawで立方体を描画させています。&lt;/p&gt;&lt;p&gt;例えば、次のようにdrawを変更した場合には、背景色が変化しながら6個の立方体が出たり引っこんだりするようになります。&lt;/p&gt;&lt;pre class="brush:cpp"&gt;void cinder_sampleApp::draw()
{
    float v = sin( getElapsedSeconds() );
    gl::clear( Color( 0.2f + red, 0.2f, v * 0.7f + 0.3f ) );

    gl::enable( GL_TEXTURE_2D );
    gl::enableDepthRead();

    mTex.bind();
    gl::setMatrices( mCam );
    glPushMatrix();
        gl::multModelView( mCubeRotation );
        gl::drawCube( Vec3f(    -v,  0.0f,  0.0f ), Vec3f( 1.0f, 1.0f, 1.0f ) );
        gl::drawCube( Vec3f(    +v,  0.0f,  0.0f ), Vec3f( 1.0f, 1.0f, 1.0f ) );
        gl::drawCube( Vec3f(  0.0f,    -v,  0.0f ), Vec3f( 1.0f, 1.0f, 1.0f ) );
        gl::drawCube( Vec3f(  0.0f,    +v,  0.0f ), Vec3f( 1.0f, 1.0f, 1.0f ) );
        gl::drawCube( Vec3f(  0.0f,  0.0f,    -v ), Vec3f( 1.0f, 1.0f, 1.0f ) );
        gl::drawCube( Vec3f(  0.0f,  0.0f,    +v ), Vec3f( 1.0f, 1.0f, 1.0f ) );
    glPopMatrix();
}
&lt;/pre&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-5JrnnFqYeok/Tdi4Qp5EzLI/AAAAAAAAAkE/zVnjWCdUnqk/s1600/cinder2.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 167px; height: 320px;" src="http://1.bp.blogspot.com/-5JrnnFqYeok/Tdi4Qp5EzLI/AAAAAAAAAkE/zVnjWCdUnqk/s320/cinder2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5609435932152614066" /&gt;&lt;/a&gt;   &lt;h4&gt;画像ファイルの利用&lt;/h4&gt;&lt;p&gt;画像ファイルをテクスチャとして利用するのは非常に簡単です。まず、いつも通りXcode上のResourcesに画像を追加しておきます。そして、それをloadResourceとloadImageによって読み込んでサーフェスを作成すればよいだけです。そのときのsetupのコードを次に示します。&lt;/p&gt;&lt;pre class="brush:cpp"&gt;#include "cinder/ImageIo.h"
void cinder_sampleApp::setup()
{
    mCubeRotation.setToIdentity();

    Surface sur( loadImage( loadResource( "texture.png" ) ) );
    mTex = gl::Texture( sur );
}
&lt;/pre&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-dze3zou-ej4/Tdi4QwskmBI/AAAAAAAAAkM/e5BbagdD67c/s1600/cinder3.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 166px; height: 320px;" src="http://2.bp.blogspot.com/-dze3zou-ej4/Tdi4QwskmBI/AAAAAAAAAkM/e5BbagdD67c/s320/cinder3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5609435933979219986" /&gt;&lt;/a&gt;  &lt;h4&gt;マルチタッチの利用&lt;/h4&gt;&lt;p&gt;マルチタッチも可能で、次のようなコードで使うことができます (クラスcinder_sampleAppへ宣言追加も必要です)。&lt;/p&gt;&lt;pre class="brush:cpp"&gt;void cinder_sampleApp::touchesBegan( TouchEvent event )
{
    for ( int i = 0; i &amp;lt; event.getTouches().size(); ++i )
        console() &amp;lt;&amp;lt; "Touch #" &amp;lt;&amp;lt; i &amp;lt;&amp;lt; " @ " &amp;lt;&amp;lt; event.getTouches()[i].getPos() &amp;lt;&amp;lt; std::endl;
}
&lt;/pre&gt;&lt;p&gt;これによって、タッチしたときにデバッグコンソールに次のように表示するようになります。&lt;/p&gt;&lt;pre&gt;&lt;code&gt;Touch #0 @ [281,317]
Touch #1 @ [39,163]
&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;まとめ&lt;/h4&gt;&lt;p&gt;CinderのiPhone向けのアプリケーションを作成する手順について簡単に説明しました。チュートリアルやサンプルプロジェクトもZipファイル内にたくさんあるので参考になると思います。デバイス向き検出ができなかったりとiPhoneとiPadへの対応はまだ十分ではないという印象を受けましたが、今後の発展が期待できるライブラリであると思います。&lt;/p&gt;&lt;h4&gt;関連項目&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://libcinder.org/"&gt;Cinder&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://libcinder.org/docs/v0.8.2/hello_cinder.html"&gt;Cinderのチュートリアル&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5191809332257264217-5024868248966858260?l=safx-dev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/6U7D8-nvamVLhfREblo6LxQqgDM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/6U7D8-nvamVLhfREblo6LxQqgDM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/6U7D8-nvamVLhfREblo6LxQqgDM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/6U7D8-nvamVLhfREblo6LxQqgDM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/TFCRl/~4/O5RxODvmzJw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://safx-dev.blogspot.com/feeds/5024868248966858260/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://safx-dev.blogspot.com/2011/05/cinderiphone.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/5024868248966858260?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/5024868248966858260?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/TFCRl/~3/O5RxODvmzJw/cinderiphone.html" title="CinderによるiPhoneアプリケーションの作成について" /><author><name>safx developer</name><uri>http://www.blogger.com/profile/13931453776402259724</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/-xmu-GKy-rZo/TY10GvG4LYI/AAAAAAAAAgo/2rul0qNef4Q/s220/%255Bsafx%255D%2B-%2B%25E3%2581%2595%25E3%2581%25B5%25E9%2596%258B%25E7%2599%25BA%25E8%2580%2585.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-5JrnnFqYeok/Tdi4Qp5EzLI/AAAAAAAAAkE/zVnjWCdUnqk/s72-c/cinder2.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://safx-dev.blogspot.com/2011/05/cinderiphone.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEYNQX05cCp7ImA9WhdWEEg.&quot;"><id>tag:blogger.com,1999:blog-5191809332257264217.post-8298437317576938069</id><published>2011-05-01T23:37:00.005+09:00</published><updated>2011-09-03T21:16:30.328+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-03T21:16:30.328+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="拡張" /><category scheme="http://www.blogger.com/atom/ns#" term="Python" /><category scheme="http://www.blogger.com/atom/ns#" term="Mercurial" /><title>Mercurial拡張の書きかたについて</title><content type="html">&lt;p&gt;MercurialがPythonで書かれていることもあり、単純なMercurial拡張を自分で書くのは意外と簡単です。この記事では簡単なMercurial拡張を作成してhgコマンドから呼び出す方法を簡単に説明します。&lt;/p&gt;&lt;p&gt;なお、Mercurialの内部APIを用いた場合には、そのコードはMercurialのライセンス (GPL) に従うことになるので注意してください。&lt;/p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-Jg5SgTCKVII/Tb1wTtV7SgI/AAAAAAAAAi8/pqtJE1bfI0Q/s1600/Screen%2Bshot%2B2011-04-30%2Bat%2B23.58.35.png"&gt;&lt;img style="width: 320px; height: 293px;" src="http://1.bp.blogspot.com/-Jg5SgTCKVII/Tb1wTtV7SgI/AAAAAAAAAi8/pqtJE1bfI0Q/s320/Screen%2Bshot%2B2011-04-30%2Bat%2B23.58.35.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5601756995410151938" /&gt;&lt;/a&gt;  &lt;a name='more'&gt;&lt;/a&gt; &lt;h4&gt;スクリプトとしての起動&lt;/h4&gt;&lt;p&gt;Mercurial拡張は単にMercurial APIを利用しているPythonのモジュールです。その出発点は次のようなスクリプトになります。&lt;/p&gt;&lt;pre class="brush:python"&gt;#!/usr/bin/python
# -*- coding: utf-8 -*-

from mercurial import ui, hg

def print_users(ui, repo, **opts):
    print repo

if __name__ == '__main__':
    ui   = ui.ui()
    repo = hg.repository(ui, ".") # カレントディレクトリのrepoオブジェクト
    print_users(ui, repo)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;uiはユーザとのインタラクションを行うためのオブジェクトですが、単純な拡張であれば不要であるためここで説明しません。repoはリポジトリオブジェクトで、ここではカレントディレクトリのリポジトリを取得しています。また、後で拡張として呼び出せるようにするため、関数print_usersは3引数を取るようにしています。なお、optsはオプションのためのもので、この記事では使用しないため詳細は省略します。&lt;/p&gt;&lt;p&gt;このスクリプトを作業ディレクトリで実行すると次のようになります。&lt;/p&gt;&lt;pre class="brush:bash"&gt;&amp;gt; python ~/src/print_users.py
&amp;lt;hgext.mq.mqrepo object at 0x101779890&amp;gt;
&lt;/pre&gt;&lt;h4&gt;hgからの実行&lt;/h4&gt;&lt;p&gt;先ほどのスクリプトをhgから実行できるようにしてみましょう。まず、.hgrc内のextensionsセクションに次のような行を追加します。&lt;/p&gt;&lt;pre&gt;&lt;code&gt;[extensions]
print_users=~/src/print_users.py
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;次に、先ほどのスクリプトの末尾に次のようにディクショナリcmdtableを書きます。これはコマンドラインオプションを解釈して適切に処理させるためのテーブルです。&lt;/p&gt;&lt;pre class="brush:python"&gt;cmdtable = {
    # "コマンド名": (関数, オプション, ヘルプ)
    "users":     (print_users, [], "print users")
}
&lt;/pre&gt;&lt;p&gt;これによって拡張をhgから呼び出すことができます。&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&amp;gt; hg users 
&amp;lt;hgext.mq.mqrepo object at 0x1011db510&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;コードの追加&lt;/h4&gt;&lt;p&gt;さらに、関数print_usersを書き替えて、関数get_user_countを追加します。この関数はリビジョン0からtipまでの各リビジョンのユーザを調べていきます。関数print_usersではこれを利用して、コミット回数の多いユーザのトップ10を表示させます。&lt;/p&gt;&lt;pre class="brush:python"&gt;def print_users(ui, repo, **opts):
    user_count = get_user_count(repo)
    l = sorted(user_count, lambda i,j:user_count[j] - user_count[i])[:10]
    for i in l:
        print user_count[i], i

def get_user_count(repo):
    tip     = repo.changectx("tip")
    tip_rev = tip.rev()

    user_count = {}
    for i in range(tip_rev):
        ctx = repo.changectx(i)
        user = ctx.user()
        if user_count.has_key(user):
            user_count[user] += 1
        else:
            user_count[user]  = 1

    return user_count;
&lt;/pre&gt;&lt;p&gt;例えば、ある時点におけるMercurialリポジトリ上で実行すると次のような結果となりました (メールアドレス部は変更しています)。&lt;/p&gt;&lt;pre class="brush:bash"&gt;&amp;gt; hg users
2324 Matt Mackall &amp;lt;mpm@example.com&amp;gt;
965 Thomas Arendsen Hein &amp;lt;thomas@example.com&amp;gt;
917 Benoit Boissinot &amp;lt;benoit.boissinot@example.com&amp;gt;
913 Martin Geisler &amp;lt;mg@example.com&amp;gt;
862 Patrick Mezard &amp;lt;pmezard@example.com&amp;gt;
768 mpm@example.com
617 Brendan Cully &amp;lt;brendan@example.com&amp;gt;
533 Alexis S. L. Carvalho &amp;lt;alexis@example.com&amp;gt;
498 Dirkjan Ochtman &amp;lt;dirkjan@example.com&amp;gt;
476 Vadim Gelfer &amp;lt;vadim.gelfer@example.com&amp;gt;
&lt;/pre&gt;&lt;h4&gt;debugshell&lt;/h4&gt;&lt;p&gt;拡張を書くときに便利なインタラクティブな環境としてdebugshell拡張が用意されています。これは、Mac portsの場合には.hgrcのextensionsセクションにdebugshell=/opt/local/share/mercurial/contrib/debugshell.pyと書くだけでよいです。&lt;/p&gt;&lt;pre class="brush:bash"&gt;&amp;gt; hg debugshell
loaded repo : /Users/foobar/src/mysample
using source: /opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/mercurial
&amp;gt;&amp;gt;&amp;gt; repo
&amp;lt;hgext.mq.mqrepo object at 0x1011db5d0&amp;gt;
&amp;gt;&amp;gt;&amp;gt; cl
&amp;lt;mercurial.changelog.changelog object at 0x1011fa5d0&amp;gt;
&amp;gt;&amp;gt;&amp;gt; mercurial
&amp;lt;proxied module 'mercurial'&amp;gt;
&lt;/pre&gt;&lt;h4&gt;まとめ&lt;/h4&gt;&lt;p&gt;Mercurial拡張を作成する方法を説明しました。&lt;/p&gt;&lt;h4&gt;関連記事&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://safx-dev.blogspot.com/2011/03/mercurial.html"&gt;さふ開発日記: Mercurialのリポジトリ内のデータについて&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://mercurial.selenic.com/wiki/UsingExtensions"&gt;Mercurial拡張のページ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://mercurial.selenic.com/wiki/WritingExtensions"&gt;拡張の書き方&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://mercurial.selenic.com/wiki/MercurialApi"&gt;Mercurial API&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5191809332257264217-8298437317576938069?l=safx-dev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/lbTfW-C5G9Y8x4QuhC631cWEubo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/lbTfW-C5G9Y8x4QuhC631cWEubo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/lbTfW-C5G9Y8x4QuhC631cWEubo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/lbTfW-C5G9Y8x4QuhC631cWEubo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/TFCRl/~4/NYhglw6Svxk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://safx-dev.blogspot.com/feeds/8298437317576938069/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://safx-dev.blogspot.com/2011/05/mercurial.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/8298437317576938069?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/8298437317576938069?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/TFCRl/~3/NYhglw6Svxk/mercurial.html" title="Mercurial拡張の書きかたについて" /><author><name>safx developer</name><uri>http://www.blogger.com/profile/13931453776402259724</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/-xmu-GKy-rZo/TY10GvG4LYI/AAAAAAAAAgo/2rul0qNef4Q/s220/%255Bsafx%255D%2B-%2B%25E3%2581%2595%25E3%2581%25B5%25E9%2596%258B%25E7%2599%25BA%25E8%2580%2585.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-Jg5SgTCKVII/Tb1wTtV7SgI/AAAAAAAAAi8/pqtJE1bfI0Q/s72-c/Screen%2Bshot%2B2011-04-30%2Bat%2B23.58.35.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://safx-dev.blogspot.com/2011/05/mercurial.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEQBQX49eyp7ImA9WhdWEEg.&quot;"><id>tag:blogger.com,1999:blog-5191809332257264217.post-7104338711280911359</id><published>2011-03-26T19:07:00.008+09:00</published><updated>2011-09-03T21:19:10.063+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-03T21:19:10.063+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Revlog" /><category scheme="http://www.blogger.com/atom/ns#" term="Mercurial" /><title>Mercurialのリポジトリ内のデータについて</title><content type="html">&lt;p&gt;Mercurialではリポジトリであるディレクトリ.hgの中に管理している全ファイルの履歴に関するデータが入っています。それがどのように保存されているのかを例を用いて簡単に紹介します。&lt;/p&gt;&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-f23ly_EFXzE/TYy3pHn6veI/AAAAAAAAAgI/AAUDYVkoq5w/s1600/P3209895.jpg"&gt;&lt;img  src="http://1.bp.blogspot.com/-f23ly_EFXzE/TYy3pHn6veI/AAAAAAAAAgI/AAUDYVkoq5w/s400/P3209895.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5588043154708938210" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;a name='more'&gt;&lt;/a&gt; &lt;h4&gt;概要&lt;/h4&gt;&lt;p&gt;ディレクトリ.hg内にはいろいろファイルが含まれています。ほとんどのデータは.hg/store内にあり、その中にチェンジセット、マニフェスト、ファイルの履歴が含まれています。&lt;/p&gt;&lt;ul&gt;&lt;li&gt;changelog &lt;ul&gt;&lt;li&gt;ファイル: .hg/store/00changelog.iと.hg/store/00changelog.d&lt;/li&gt;
&lt;li&gt;マニフェストIDとコミット者、コメント、変更したファイル一覧などの各チェンジセットの情報を持ちます。&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;manifest &lt;ul&gt;&lt;li&gt;ファイル: .hg/store/00manifest.iと.hg/store/00manifest.d&lt;/li&gt;
&lt;li&gt;リポジトリで管理しているファイルの一覧です。&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;filelog &lt;ul&gt;&lt;li&gt;ファイル: .hg/store/data内にある、.iと.dファイル。&lt;/li&gt;
&lt;li&gt;1ファイルの履歴です。&lt;/li&gt;
&lt;li&gt;ある&lt;a href="http://mercurial.selenic.com/wiki/CaseFoldingPlan"&gt;文字列をエンコードする方法&lt;/a&gt;に従ってパスをエンコードする。&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;h4&gt;例&lt;/h4&gt;&lt;p&gt;次のようなリビジョングラフを持つリポジトリがあるとします。&lt;/p&gt;&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-qdd-Woi0bJg/TYy3pUO3m_I/AAAAAAAAAgQ/jHT-OCzBMKI/s1600/hg_cset.png"&gt;&lt;img  src="http://3.bp.blogspot.com/-qdd-Woi0bJg/TYy3pUO3m_I/AAAAAAAAAgQ/jHT-OCzBMKI/s400/hg_cset.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5588043158093536242" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;この時点でのリポジトリの.hg/store内のファイルは次のようなものが含まれています。&lt;/p&gt;&lt;ul&gt;&lt;li&gt;チェンジログ 00changelog.i&lt;/li&gt;
&lt;li&gt;マニフェスト 00manifest.i&lt;/li&gt;
&lt;li&gt;ファイルログ data/&lt;em&gt;r&lt;/em&gt;e&lt;em&gt;a&lt;/em&gt;d&lt;em&gt;m&lt;/em&gt;e.i&lt;/li&gt;
&lt;li&gt;ファイルログ data/hello.c.i&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;まずチェンジログの情報を見てみましょう。これには、hg debugindexを用います。&lt;/p&gt;&lt;pre class="brush:bash"&gt;&amp;gt; hg debugindex .hg/store/00changelog.i
   rev    offset  length   base linkrev nodeid       p1           p2
     0         0      93      0       0 534511281f45 000000000000 000000000000
     1        93     101      0       1 6292b118cc08 534511281f45 000000000000
     2       194      96      2       2 027b81ff6ac3 6292b118cc08 000000000000
     3       290      95      3       3 199d45709b22 534511281f45 000000000000
     4       385      90      4       4 f0df7b3fe2df 027b81ff6ac3 199d45709b22
&lt;/pre&gt;&lt;p&gt;この中で、revはリビジョン番号、nodeidはチェンジセットIDとなっています。そして、p1とp2は親のチェンジセットIDであり、rev 4では2つの親を持っており、全体としては上のリビジョングラフと同じ関係になっていることがわかります。&lt;/p&gt;&lt;p&gt;特定のリビジョンにおける、より詳しい情報を見るにはhg debugdataを用います。チェンジセットのリビジョン4の出力結果は次のようになります。出力結果は1行目からマニフェストID、メールアドレス、日時、変更のあったファイル(空行まで)、コミットメッセージになっています。&lt;/p&gt;&lt;pre class="brush:bash"&gt;&amp;gt; hg debugdata .hg/store/00changelog.i 4
b6323997ef85fb93cb3dc645ae6ca7e2b8161cea
foobar@example.com
1300547811 -32400
hello.c

Merge
&lt;/pre&gt;&lt;p&gt;続いてマニフェストの情報を見ます。hg debugindexでチェンジログのときと同じような情報を見ることができます。マニフェストでもリビジョンごとにチェンジログとは異なるIDが振られていますが、リビジョンの親子関係が同じであることがわかります。また、先ほどチェンジセットのリビジョン4の情報にあったマニフェストIDのb6323997ef85がマニフェストのrev 4に対応していることがわかるでしょう。&lt;/p&gt;&lt;pre class="brush:bash"&gt;&amp;gt; hg debugindex .hg/store/00manifest.i 
   rev    offset  length   base linkrev nodeid       p1           p2
     0         0      50      0       0 47eb6be8d357 000000000000 000000000000
     1        50      50      1       1 2f3afa09f4f8 47eb6be8d357 000000000000
     2       100      60      1       2 b0e834b727ad 2f3afa09f4f8 000000000000
     3       160      50      3       3 08b4087d6b4f 47eb6be8d357 000000000000
     4       210      96      3       4 b6323997ef85 b0e834b727ad 08b4087d6b4f
&lt;/pre&gt;&lt;p&gt;マニフェストの詳細情報を見るのにはhg debugindexを利用してもよいですが、hg --debug manifestのほうがより詳細な情報を見ることができます。次の例ではマニフェストのrev 4に含まれるファイルの情報を出力しています。&lt;/p&gt;&lt;pre class="brush:cpp"&gt;&amp;gt; hg --debug manifest 4
94e1e9804aa05b8a7874c4316c7eec59e87c9c36 644   README
600deb1ed703b78db22e5020acb13242430c5543 644   hello.c
&lt;/pre&gt;&lt;p&gt;ファイルhello.cに対するファイルログhello.c.iの概要は次の通りです。マニフェストに出現している600deb1ed703がrev 3にあるのがわかります。&lt;/p&gt;&lt;pre class="brush:bash"&gt;&amp;gt; hg debugindex .hg/store/data/hello.c.i 
   rev    offset  length   base linkrev nodeid       p1           p2
     0         0      71      0       0 edb191afdd3d 000000000000 000000000000
     1        71      43      0       1 ec1d99d13de0 edb191afdd3d 000000000000
     2       114      26      0       3 8e675a97a9fe edb191afdd3d 000000000000
     3       140      43      0       4 600deb1ed703 ec1d99d13de0 8e675a97a9fe
&lt;/pre&gt;&lt;p&gt;hg debugdataを用いると指定したリビジョンのデータを取得することができます。&lt;/p&gt;&lt;pre class="brush:cpp"&gt;&amp;gt; hg debugdata .hg/store/data/hello.c.i 3
#include &amp;lt;stdio.h&amp;gt;

int main(int argc, char** argv) {
    printf("Hello, world!\n");
    return 1;
}
&lt;/pre&gt;&lt;p&gt;ファイルREADMEは追加したとき以外の変更がないのでリビジョン0のままです。&lt;/p&gt;&lt;pre class="brush:bash"&gt;&amp;gt; hg debugindex .hg/store/data/_r_e_a_d_m_e.i
   rev    offset  length   base linkrev nodeid       p1           p2
     0         0      22      0       2 94e1e9804aa0 000000000000 000000000000
&lt;/pre&gt;&lt;p&gt;これらのファイルのリビジョン同士の関係を示したものが次の図です。黒矢印はファイルのリビジョン関係を、赤点線の矢印は(チェンジセットのリビジョン4における)参照可能な関係を示しています。hg updateなどではこの矢印を辿ることで特定リビジョンのファイルを取得しています。&lt;/p&gt;&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-d147O19Jxk0/TYy3puRGXUI/AAAAAAAAAgY/2W8_58mCemo/s1600/hg.png"&gt;&lt;img  src="http://3.bp.blogspot.com/-d147O19Jxk0/TYy3puRGXUI/AAAAAAAAAgY/2W8_58mCemo/s480/hg.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5588043165082213698" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;h4&gt;Revlog形式&lt;/h4&gt;&lt;p&gt;チェンジログ、マニフェスト、ファイルログはファイルの履歴を保存するためにRevlogと呼ばれるMercurial独自のフォーマットで記録されています。Revlogには次のような特徴があります。&lt;/p&gt;&lt;ul&gt;&lt;li&gt;データファイルとインデックスファイルに分かれており、それぞれ拡張子 .d と .i を持つ&lt;/li&gt;
&lt;li&gt;データとインデックスはファイル末尾に追加されていく (トランザクション化が容易になる)&lt;/li&gt;
&lt;li&gt;直前のバージョンからのバイナリでの差分 (difflibで用いられているRatcliff-Obershelpアルゴリズム) によるデータを圧縮したものを持つ。ただし、再構築に必要なデータ量がしきい値を超えたときは差分ではなくフルデータを取るようにする (リビジョン数によらない)&lt;/li&gt;
&lt;li&gt;小さいサイズのファイルの場合.dはなく.iの中に.dのデータが含まれている (.iと.dが交互に出現する; データインタリーブ)&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;コマンドラインdebugindexでインデックスファイルを、debugdataでデータファイルを見ることができます。これらをRevlogのファイル構造のサンプルが次の図です。例えば、リビジョン12のデータを取得するためには、まずベースとなるリビジョン10からフルデータを取得し、そこからリビジョン11と12の差分データを順番に適用することで得られます。&lt;/p&gt;&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-1eowKhIHsao/TY28Y_G0E4I/AAAAAAAAAhg/1La2YdiBqVo/s1600/hg_revlog.png"&gt;&lt;img  src="http://3.bp.blogspot.com/-1eowKhIHsao/TY28Y_G0E4I/AAAAAAAAAhg/1La2YdiBqVo/s480/hg_revlog.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5588329850079548290" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;なお、Revlogのインデックスファイルは次のようなフォーマットになっています。&lt;/p&gt;&lt;ul&gt;&lt;li&gt;6 bytes: 差分データ開始位置のオフセット&lt;/li&gt;
&lt;li&gt;2 bytes: フラグ&lt;/li&gt;
&lt;li&gt;4 bytes: 差分データの圧縮サイズ&lt;/li&gt;
&lt;li&gt;4 bytes: オリジナルデータのサイズ&lt;/li&gt;
&lt;li&gt;4 bytes: ベースリビジョン: どのリビジョンのフルデータから差分を適用すればよいか&lt;/li&gt;
&lt;li&gt;4 bytes: リンクリビジョン: どのチェンジセットに対するデータなのかをチェンジセットのリビジョン番号で示す&lt;/li&gt;
&lt;li&gt;4 bytes: 親1のリビジョン&lt;/li&gt;
&lt;li&gt;4 bytes: 親2のリビジョン&lt;/li&gt;
&lt;li&gt;32 bytes: ノードID: ユニーク識別子で改竄検知などにも用いられる (データと親ノードIDによるハッシュ値)&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;これを見ればわかる通り、各ファイルはそれぞれリビジョンごとにユニークなノードIDを持ち、最大2つまでの親を取ることができます。Mercurialではマージ操作では2つ以上のファイルからマージされることはないため、このようにシンプルなデータ構造となっています。&lt;/p&gt;&lt;p&gt;また、これによって各リビジョンごとのインデックスのサイズが固定長になるため、あるリビジョンのインデックスを得るためには決まった位置へファイルシークするだけで済みます (データインタリーブしている場合を除く)。&lt;/p&gt;&lt;h4&gt;まとめ&lt;/h4&gt;&lt;p&gt;Mercurialのリポジトリ内のデータについて簡単に紹介しました。&lt;/p&gt;&lt;h4&gt;関連項目&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://hgbook.red-bean.com/read/behind-the-scenes.html#x8-640004"&gt;Mercurial: The Definitive Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://mercurial.selenic.com/wiki/Revlog"&gt;Revlog - Mercurial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://mercurial.selenic.com/wiki/Presentations?action=AttachFile&amp;amp;do=view&amp;amp;target=ols-mercurial-paper.pdf"&gt;Mercurial Revloog (pdf)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5191809332257264217-7104338711280911359?l=safx-dev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/OqcEl3zYr70AV9PuMuSpdx7jXEo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/OqcEl3zYr70AV9PuMuSpdx7jXEo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/OqcEl3zYr70AV9PuMuSpdx7jXEo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/OqcEl3zYr70AV9PuMuSpdx7jXEo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/TFCRl/~4/P_pYAP8vFyw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://safx-dev.blogspot.com/feeds/7104338711280911359/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://safx-dev.blogspot.com/2011/03/mercurial.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/7104338711280911359?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/7104338711280911359?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/TFCRl/~3/P_pYAP8vFyw/mercurial.html" title="Mercurialのリポジトリ内のデータについて" /><author><name>safx developer</name><uri>http://www.blogger.com/profile/13931453776402259724</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/-xmu-GKy-rZo/TY10GvG4LYI/AAAAAAAAAgo/2rul0qNef4Q/s220/%255Bsafx%255D%2B-%2B%25E3%2581%2595%25E3%2581%25B5%25E9%2596%258B%25E7%2599%25BA%25E8%2580%2585.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-f23ly_EFXzE/TYy3pHn6veI/AAAAAAAAAgI/AAUDYVkoq5w/s72-c/P3209895.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://safx-dev.blogspot.com/2011/03/mercurial.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEMAQn87fyp7ImA9WhdWEEg.&quot;"><id>tag:blogger.com,1999:blog-5191809332257264217.post-3971652807186959473</id><published>2011-02-28T01:11:00.009+09:00</published><updated>2011-09-03T21:20:43.107+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-03T21:20:43.107+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="NSObject" /><category scheme="http://www.blogger.com/atom/ns#" term="API" /><category scheme="http://www.blogger.com/atom/ns#" term="Mac" /><category scheme="http://www.blogger.com/atom/ns#" term="ランタイムAPI" /><category scheme="http://www.blogger.com/atom/ns#" term="メッセージ転送" /><title>NSObjectを継承しないクラスをランタイムAPIで作成する方法について</title><content type="html">&lt;p&gt;Objective-CにはランタイムAPIが用意されており、これを利用することでObjective-Cのクラスやオブジェクトを作成や操作を実行時に行うことができます。&lt;/p&gt;&lt;p&gt;本記事では新しいクラスをObjective-CランタイムAPIで作成して利用してみます。 このとき、新しいクラスをNSObjectから継承せずに作成してみることで、どのような問題が起こるのかを述べます。&lt;/p&gt;&lt;p&gt;Objective-CランタイムAPIについてはAppleのリファレンス「&lt;a 
href="http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html#//apple_ref/doc/uid/TP40001418"&gt;Objective-C Runtime Reference&lt;/a&gt;」を参照してください。 また、Objective-Cランタイムシステムに興味のある方は、マイコミジャーナルのコラム「&lt;a href="http://journal.mycom.co.jp/column/objc/index.html"&gt;ダイナミックObjective-C&lt;/a&gt;」の14〜31回を参照してください。&lt;/p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://picasaweb.google.com/lh/photo/zu9hR5WDg9PZaaGIs6LhWg?feat=directlink"&gt;&lt;img src="http://1.bp.blogspot.com/-Z2uN8arX5q8/TWvIUDabKTI/AAAAAAAAAdU/Xo5CqwnOUYo/s320/P1038424.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5578772810267568434" /&gt;&lt;/a&gt; &lt;a name='more'&gt;&lt;/a&gt;  &lt;h4&gt;Objective-CランタイムAPIによるメソッドの列挙&lt;/h4&gt;&lt;p&gt;まず、最初はObjective-CランタイムAPIを利用してクラスのメソッドを列挙してみましょう。 ちょっと適当ですが次のような関数を作成してみます。&lt;/p&gt;&lt;pre class="brush:cpp"&gt;void listMethods(id cls) {
    unsigned int method_count = 0;
    Method* m = class_copyMethodList(cls, &amp;amp;method_count);
    for (unsigned int i = 0; i &amp;lt; method_count; ++i) {
        SEL sel = method_getName(m[i]);
        const char* enc = method_getTypeEncoding(m[i]);
        char ret[256];
        method_getReturnType(m[i], ret, sizeof(ret) - 1);

        NSLog(@"method: %s (%s)", (char*)sel, enc);
    }
    free(m);
}
&lt;/pre&gt;&lt;p&gt;これを利用してNSObjectのメソッドを一覧を表示してみましょう。&lt;/p&gt;&lt;pre&gt;&lt;code&gt;listMethods([NSObject class]);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;結果は次のようになります (長いのでほんの一部だけ抜粋)。&lt;/p&gt;&lt;pre&gt;&lt;code&gt;    :
method: superclass (#8@0:4)
method: hash (I8@0:4)
method: isEqual: (c12@0:4@8)
method: init (@8@0:4)
method: description (@8@0:4)
method: isKindOfClass: (c12@0:4#8)
method: dealloc (v8@0:4)
    :
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;括弧内の文字列はタイプエンコーディングと呼ばれているもので、メソッドの引数や戻り値を示しているもので、例えば「@」はオブジェクト、「:」はセレクタを示しています (詳細は「&lt;a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html#//apple_ref/doc/uid/TP40008048-CH100-SW1"&gt;Objective-C Runtime Programming Guide: Type Encodings&lt;/a&gt;」を参照してください)。 メソッドdescriptionのタイプエンコーディングの数値を取り除いたものは「@@:」になり、 これはオブジェクトとセレクタを引数に取り、オブジェクトを戻り値にするということを示しています。&lt;/p&gt;&lt;h4&gt;Objective-CランタイムAPIによるメソッドの列挙&lt;/h4&gt;&lt;p&gt;ランタイムでObjective-Cのクラスを作成する手順は次のようになります。&lt;/p&gt;&lt;ol&gt;&lt;li&gt;objc_allocateClassPairでクラスとメタクラスをアロケートします。&lt;/li&gt;
&lt;li&gt;class&lt;em&gt;addMethodやclass&lt;/em&gt;addIvarなどでメソッドなどを追加します。インスタンスメソッドとインスタンス変数はクラスに追加し、クラスメソッドはメタクラスに追加します。なお、メタクラスは次のようにして取得することができます。 Class metaClass = object_getClass(newClass);&lt;/li&gt;
&lt;li&gt;objc_registerClassPairで登録することでlookup可能になります。&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;それでは実際にクラスを作成してみましょう。 次のコードではメソッドdescriptionを持つだけの単純なクラスMyObjectを作成しています。 なお、第1引数と第2引数はObjective-Cではselfと_cmdで参照できる隠し引数となっています。&lt;/p&gt;&lt;pre class="brush:cpp"&gt;NSString* MyObject_description(id self, SEL _cmd) {
     return @"MyObject_description is called.";
}

void MyObject_createClass() {
    Class cls = objc_allocateClassPair(nil, "MyObject", 0);
    class_addMethod(cls, @selector(description), (IMP) &amp;amp;MyObject_description, "@@:");
    objc_registerClassPair(cls);
}
&lt;/pre&gt;&lt;p&gt;これで、クラスMyObjectのインスタンスを作成して、メソッドdescriptionを実行することができます。&lt;/p&gt;&lt;pre class="brush:cpp"&gt;MyObject_createClass();

Class cls = objc_getClass("MyObject");
id obj = class_createInstance(cls, 0);
NSLog(@"%@", obj);
&lt;/pre&gt;&lt;p&gt;しかし、実行してみると、NSLogの行で落ちてしまいます。運がよければ、次のメッセージが表示されるでしょう。&lt;/p&gt;&lt;pre&gt;&lt;code&gt;*** NSInvocation: warning: object 0x9904960 of class 'MyObject' does not implement methodSignatureForSelector: -- trouble ahead
*** NSInvocation: warning: object 0x9904960 of class 'MyObject' does not implement doesNotRecognizeSelector: -- abort
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;メソッドmethodSignatureForSelector:は前回の記事「&lt;a href="http://safx-dev.blogspot.com/2011/02/forwardinvocation.html"&gt;メソッドforwardInvocation:を利用したメッセージ転送について&lt;/a&gt;」でも少し出てきましたが、対処できないメッセージを受け取ったときに呼ばれます。 このメソッドが呼ぶことができなかったため、メソッドdoesNotRecognizeSelector:を呼ぼうとし、これもないためにAbortしてしまっています。&lt;/p&gt;&lt;p&gt;(メソッドmethodSignatureForSelector:を作成してトレースしてみればわかりますが) なぜ、メソッドmethodSignatureForSelector:が呼ばれている理由は、クラスメソッドinitializeがないためです。 クラスメソッドinitializeはクラス使用の初回時に1回だけ呼ばれるメソッドで、必ず実装する必要があります。&lt;/p&gt;&lt;p&gt;また、これ以外にもメソッドdescriptionを実行するにはもう少し作業が必要です。 実は、日付などのロケールを考慮する必要のあるクラスには、メソッドdescriptionのロケール版であるdescriptionWithLocale:があり、NSLogを用いた場合にはdescriptionを呼ぶ前にdescriptionWithLocale:があるかどうかをチェックするためにrespondsToSelector:が呼ばれてしまいます。&lt;/p&gt;&lt;p&gt;これらを踏まえたコードは次のようになります。 実行すると、メソッドdescriptionWithLocale:のために MyObject_respondsToSelectorが呼ばれますが、その場合はFALSEが返されるようにしています。 なお、Cocoaの実装ではSEL型が文字列であるため、それを利用しています。&lt;/p&gt;&lt;pre class="brush:cpp"&gt;void MyObject_initialize(id self, SEL _cmd) {
     return;
}

BOOL MyObject_respondsToSelector(id self, SEL _cmd, SEL sel) {
    if (strcmp((char*) sel, "description") == 0) return TRUE;
    return FALSE;
}

void MyObject_createClass() {
    Class cls = objc_allocateClassPair(nil, "MyObject", 0);
    class_addMethod(cls, @selector(description), (IMP) &amp;amp;MyObject_description, "@@:");
    class_addMethod(cls, @selector(respondsToSelector:), (IMP) &amp;amp;MyObject_respondsToSelector, "b@::");

    Class meta = object_getClass(cls);
    class_addMethod(meta, @selector(initialize), (IMP) &amp;amp;MyObject_initialize, "v@:");
    objc_registerClassPair(cls);
}
&lt;/pre&gt;&lt;p&gt;これでめでたく表示することができました。 NSObjectから継承した場合はこのあたりの面倒さを回避することができます。&lt;/p&gt;&lt;pre&gt;&lt;code&gt;method: respondsToSelector: (b@::)
method: description (@@:)
MyObject_description is called.
&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;methodSignatureForSelector:とforwardInvocation:を利用したメッセージ処理&lt;/h4&gt;&lt;p&gt;前回の記事「&lt;a href="http://safx-dev.blogspot.com/2011/02/forwardinvocation.html"&gt;メソッドforwardInvocation:を利用したメッセージ転送について&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;
」のようにmethodSignatureForSelector:forwardInvocation:とを組み合わせることで適当に出されたメッセージに対して処理を行うことができます。&lt;/p&gt;&lt;p&gt;次のコードでは、まずメソッドMyObject&lt;em&gt;methodSignatureForSelectorでセレクタに応じた適当なタイプエンコーディングをでっちあげています。 それによって、メソッドMyObject&lt;/em&gt;forwardInvocationでのNSInvocationの値が代わりますので、今回は引数によって適当な処理をして、戻り値をNSInvocationにセットしています。&lt;/p&gt;&lt;pre class="brush:cpp"&gt;NSMethodSignature* MyObject_methodSignatureForSelector(id self, SEL _cmd, SEL sel) {
    NSString* enc = @"@@:";
    for (char* i = (char*) sel; *i != 0; ++i) {
        if (*i == ':') {
            enc = [enc stringByAppendingString:@"@"];   
        }
    }
     return [NSMethodSignature signatureWithObjCTypes:[enc UTF8String]];
}

void MyObject_forwardInvocation(id self, SEL _cmd, NSInvocation* inv) {
    SEL sel = [inv selector];

    NSMethodSignature* sig = [inv methodSignature];
    NSUInteger         num = [sig numberOfArguments];

    NSLog(@"MyObject_forwardInvocation: %s (%d args)", sel, num);

    id ret = nil;

    if (num == 2) {
        ret = [NSString stringWithFormat:@"%s", sel];
    } else if (num == 3) {
        NSString* arg1;
        [inv getArgument:&amp;amp;arg1 atIndex:2];
        ret = [NSString stringWithFormat:@"%@%s", arg1, sel];
    } else if (num == 4) {
        int arg1;
        int arg2;
        [inv getArgument:&amp;amp;arg1 atIndex:2];
        [inv getArgument:&amp;amp;arg2 atIndex:3];
        ret = [NSNumber numberWithInt:arg1 * arg2];
    }
    [inv setReturnValue:&amp;amp;ret];
}
&lt;/pre&gt;&lt;p&gt;上のコードの利用例は次のようになります。&lt;/p&gt;&lt;pre&gt;&lt;code&gt;NSLog(@"%@", [obj foobar]);
NSLog(@"%@", [obj baz:@"some-string"]);
NSLog(@"%@", [obj x:12 y:3]);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;結果は次のようになります。&lt;/p&gt;&lt;pre&gt;&lt;code&gt;MyObject_forwardInvocation: foobar (2 args)
foobar
MyObject_forwardInvocation: baz: (3 args)
some-stringbaz:
MyObject_forwardInvocation: x:y: (4 args)
&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;まとめ&lt;/h4&gt;&lt;p&gt;NSObjectを継承しないで新しいクラスをObjective-CランタイムAPIで作成する方法について述べました。&lt;/p&gt;&lt;h4&gt;関連項目&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://safx-dev.blogspot.com/2011/02/forwardinvocation.html"&gt;さふ開発日記: メソッドforwardInvocation:を利用したメッセージ転送について&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://journal.mycom.co.jp/column/objc/027/index.html"&gt;【コラム】ダイナミックObjective-C (27) ランタイムAPIでさらに動的に(1) - 動的なクラスの作成 | マイコミジャーナル&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://journal.mycom.co.jp/column/objc/018/index.html"&gt;【コラム】ダイナミックObjective-C (18) メソッドとは何か(1) - メソッド、セレクタ、メソッドの実装 | マイコミジャーナル&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html#//apple_ref/doc/uid/TP40001418"&gt;Objective-C Runtime Reference&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5191809332257264217-3971652807186959473?l=safx-dev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/HwwAFaSmfkbxJ5eHuhxGH28LIBw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/HwwAFaSmfkbxJ5eHuhxGH28LIBw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/HwwAFaSmfkbxJ5eHuhxGH28LIBw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/HwwAFaSmfkbxJ5eHuhxGH28LIBw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/TFCRl/~4/BHaU9hjYfM4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://safx-dev.blogspot.com/feeds/3971652807186959473/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://safx-dev.blogspot.com/2011/02/nsobjectapi.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/3971652807186959473?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/3971652807186959473?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/TFCRl/~3/BHaU9hjYfM4/nsobjectapi.html" title="NSObjectを継承しないクラスをランタイムAPIで作成する方法について" /><author><name>safx developer</name><uri>http://www.blogger.com/profile/13931453776402259724</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/-xmu-GKy-rZo/TY10GvG4LYI/AAAAAAAAAgo/2rul0qNef4Q/s220/%255Bsafx%255D%2B-%2B%25E3%2581%2595%25E3%2581%25B5%25E9%2596%258B%25E7%2599%25BA%25E8%2580%2585.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-Z2uN8arX5q8/TWvIUDabKTI/AAAAAAAAAdU/Xo5CqwnOUYo/s72-c/P1038424.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://safx-dev.blogspot.com/2011/02/nsobjectapi.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D08ASH88eyp7ImA9WhRWEE4.&quot;"><id>tag:blogger.com,1999:blog-5191809332257264217.post-7883395876669784142</id><published>2011-02-06T22:01:00.019+09:00</published><updated>2011-12-28T10:30:49.173+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-28T10:30:49.173+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="iPhone" /><category scheme="http://www.blogger.com/atom/ns#" term="Mac" /><category scheme="http://www.blogger.com/atom/ns#" term="メッセージ転送" /><title>メソッドforwardInvocation:を利用したメッセージ転送について</title><content type="html">&lt;p&gt;Objective-Cでは、定義していないメッセージをオブジェクトへ送信すると、通常は未定義なセレクタとして例外NSInvalidArgumentExceptionが発生します。しかし、クラスにメソッドforwardInvocation:を定義しておくと、エラー報告前にこのメソッドが呼ばれるようになります。そのため、メソッドforwardInvocation:の実装次第で、メッセージがなかったときのデフォルトの挙動を定義したり、エラー回避などを行えるようになります。&lt;/p&gt;&lt;a href="https://picasaweb.google.com/lh/photo/YDa9kmYDcoju8loiVNX9wg?feat=directlink"&gt;&lt;img src="http://3.bp.blogspot.com/-guG09v_zWwg/TVZiGDxyoPI/AAAAAAAAAbw/fVNkt-4WVx0/s320/P2069781.jpeg" border="0" alt=""id="BLOGGER_PHOTO_ID_5572749445150449906" /&gt;&lt;/a&gt;  &lt;p&gt;この記事では、forwardInvocation:を利用したメッセージ転送や多重継承について述べます。なお、詳細については、Appleの「Objective-C Runtime Programming Guide」の「&lt;a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtForwarding.html#//apple_ref/doc/uid/TP40008048-CH105-SW1"&gt;Message Forwarding&lt;/a&gt;」の章や、サンプルコード「&lt;a href="http://developer.apple.com/library/mac/#samplecode/ForwardInvocation/Introduction/Intro.html"&gt;ForwardInvocation&lt;/a&gt;」を参照してください。&lt;/p&gt;&lt;a name='more'&gt;&lt;/a&gt;  &lt;h4&gt;メッセージ転送の例&lt;/h4&gt;&lt;p&gt;メソッドforwardInvocation:は名前の通りメッセージを他のオブジェクトに転送するのが一般的な使いかたです。例えば次のようにメソッドが複数あるオブジェクトのために転送メソッドを複数書く必要がある場合には、forwardInvocation:を使うとよいでしょう。&lt;/p&gt;&lt;pre class="brush:cpp"&gt;@interface Base : NSObject { }
- (void)foo;
- (void)bar;
- (void)baz;
@end

@implementation Base
- (void)foo {
    NSLog(@"%@: Foo", self);
}
- (void)bar {
    NSLog(@"%@: Bar", self);
}
- (void)baz {
    NSLog(@"%@: Baz", self);
}
@end
&lt;/pre&gt;&lt;p&gt;転送のためのクラスは次のように定義します。なお、methodSignatureForSelector:を定義しているのは、これがない場合とforwardInvocation:が呼ばれないからです。また、メッセージに対処できないときは通常はsuperのforwardInvocation:を呼び出すとよいみたいです。&lt;/p&gt;&lt;pre class="brush:cpp"&gt;@interface ForwardObject : NSObject {
    id _target;
}
@end

@implementation ForwardObject
- (id)initWithTarget:(id)target {
    if (self = [super init]) {
        _target = target;
    }
    return self;
}
- (void)forwardInvocation:(NSInvocation*)inv {
    if ([_target respondsToSelector:[inv selector]]) {
        [inv invokeWithTarget:_target];
    } else {
        [super doesNotRecognizeSelector:[inv selector]];
    }
}
- (NSMethodSignature*)methodSignatureForSelector:(SEL)sel {
    return [_target methodSignatureForSelector:sel];
}
@end
&lt;/pre&gt;&lt;p&gt;上記のクラスForwardObjectを用いて次のように呼び出すことにします。&lt;/p&gt;&lt;pre class="brush:cpp"&gt;Base* base = [[Base alloc] init];
[base foo];

ForwardObject* obj = [[ForwardObject alloc] initWithTarget:base];
[obj foo];
[obj bar];
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;その結果は次のようになります。ForwordObjectが持っていないメソッドが呼び出せていることがわかります。&lt;/p&gt;&lt;pre&gt;&amp;lt;Base: 0x4e17d90&amp;gt;: Foo
&amp;lt;Base: 0x4e17d90&amp;gt;: Foo
&amp;lt;Base: 0x4e17d90&amp;gt;: Bar
&lt;/pre&gt;&lt;p&gt;また、次のようにNSTimerを利用することで、ターゲットへのすべてのメッセージを5秒遅延させることができます (意味があるかどうかわかりませんが)。&lt;/p&gt;&lt;pre class="brush:cpp"&gt;@interface LazyObject : ForwardObject {}
@end

@implementation LazyObject
- (void)forwardInvocation:(NSInvocation*)inv {
    if ([_target respondsToSelector:[inv selector]]) {
        [inv setTarget:_target];
        [NSTimer scheduledTimerWithTimeInterval:5 invocation:inv repeats:NO];
    } else {
        [super doesNotRecognizeSelector:[inv selector]];
    }
}
@end
&lt;/pre&gt;&lt;h4&gt;多重継承&lt;/h4&gt;&lt;p&gt;先ほどの例とほとんどコードは変わりませんが、メソッドforwardInvocation:を利用すると多重継承が実現できます。C++の多重継承と違うのは、ダイヤモンド継承などで同名のメソッドがある場合には継承が優先されることです。&lt;/p&gt;&lt;p&gt;さらに、respondsToSelector:、isKindOfClass:、conformsToProtocol:、instancesRespondToSelector:などのメソッドを定義するとより多重継承らしく見えるようになります。&lt;/p&gt;&lt;pre class="brush:cpp"&gt;@interface Derived : Base {
    SubBase* _subBase;
}
@end

@implementation Derived
- (id)init {
    if (self = [super init]) {
        _subBase = [[SubBase alloc] init];
    }
    return self;
}
- (void)forwardInvocation:(NSInvocation*)inv {
    if ([_subBase respondsToSelector:[inv selector]]) {
        [inv invokeWithTarget:_subBase];
    } else {
        [super doesNotRecognizeSelector:[inv selector]];
    }
}
- (NSMethodSignature*)methodSignatureForSelector:(SEL)sel {
    return [_subBase methodSignatureForSelector:sel];
}
- (void)dealloc {
    [_subBase release];
    [super dealloc];
}
@end
&lt;/pre&gt;&lt;h4&gt;まとめ&lt;/h4&gt;&lt;p&gt;forwardInvocation:を利用したメッセージ転送や多重継承について述べました。&lt;/p&gt;&lt;h4&gt;関連項目&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://journal.mycom.co.jp/column/objc/045/index.html"&gt;【コラム】ダイナミックObjective-C (45) AspectCocoa (3) - フォワーディングとポージングの利用 | マイコミジャーナル&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtForwarding.html#//apple_ref/doc/uid/TP40008048-CH105-SW1"&gt;Objective-C Runtime Programming Guide: Message Forwarding&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html#//apple_ref/occ/cl/NSObject"&gt;NSObject Class Reference&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5191809332257264217-7883395876669784142?l=safx-dev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/pCGmtasoOdKSHgP8VSeQcic9RnM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/pCGmtasoOdKSHgP8VSeQcic9RnM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/pCGmtasoOdKSHgP8VSeQcic9RnM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/pCGmtasoOdKSHgP8VSeQcic9RnM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/TFCRl/~4/Abs71bGQYQg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://safx-dev.blogspot.com/feeds/7883395876669784142/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://safx-dev.blogspot.com/2011/02/forwardinvocation.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/7883395876669784142?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/7883395876669784142?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/TFCRl/~3/Abs71bGQYQg/forwardinvocation.html" title="メソッドforwardInvocation:を利用したメッセージ転送について" /><author><name>safx developer</name><uri>http://www.blogger.com/profile/13931453776402259724</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/-xmu-GKy-rZo/TY10GvG4LYI/AAAAAAAAAgo/2rul0qNef4Q/s220/%255Bsafx%255D%2B-%2B%25E3%2581%2595%25E3%2581%25B5%25E9%2596%258B%25E7%2599%25BA%25E8%2580%2585.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-guG09v_zWwg/TVZiGDxyoPI/AAAAAAAAAbw/fVNkt-4WVx0/s72-c/P2069781.jpeg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://safx-dev.blogspot.com/2011/02/forwardinvocation.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkUDSHc4cSp7ImA9Wx9VFEU.&quot;"><id>tag:blogger.com,1999:blog-5191809332257264217.post-8469736744638779493</id><published>2011-01-31T23:24:00.003+09:00</published><updated>2011-01-31T23:31:19.939+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-01-31T23:31:19.939+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="コンパイラ" /><category scheme="http://www.blogger.com/atom/ns#" term="静的単一代入" /><category scheme="http://www.blogger.com/atom/ns#" term="アセンブラ" /><category scheme="http://www.blogger.com/atom/ns#" term="SSA" /><category scheme="http://www.blogger.com/atom/ns#" term="LLVM" /><title>LLVMのアセンブリコードによるプログラム</title><content type="html">&lt;p&gt;&lt;a href="http://llvm.org/"&gt;LLVM&lt;/a&gt; [&lt;a href="http://ja.wikipedia.org/wiki/Low_Level_Virtual_Machine"&gt;Wikipedia&lt;/a&gt;]
はコンパイラのための基盤記述であり、&lt;a href="http://clang.llvm.org/"&gt;clang&lt;/a&gt;などに用いられています。&lt;/p&gt;

&lt;p&gt;この記事では今さらですが、LLVMのアセンブリコードによるプログラムをいくつか試してみます。
なお、LLVMのアセンブリコードの詳細については「&lt;a href="http://llvm.org/docs/LangRef.html"&gt;LLVM Assembly Language Reference Manual&lt;/a&gt;」を参照してください。&lt;/p&gt;

&lt;p&gt;&lt;a href="http://picasaweb.google.com/lh/photo/OeZqAtn3ZYyjZzl-EMFsbg?feat=embedwebsite"&gt;&lt;img src="http://lh6.ggpht.com/_XbtP-rrPvTg/TUbF19FspNI/AAAAAAAAAZc/Cp61R2emm9g/s400/P1319752-3.jpg" height="300" width="400" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;a name='more'&gt;&lt;/a&gt;

&lt;p&gt;次の例は単純なHello worldの例です (helloworld.ll)。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@HW = internal constant [14 x i8] c"Hello world!\0A\00"

declare i32 @puts(i8*)

define i32 @main() {
  %cast_hw = getelementptr [14 x i8]* @HW, i32 0, i32 0
  call i32 @puts(i8* %cast_hw)
  ret i32 0
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;ここで、@で始まる識別子はグローバル変数、
%で始まる識別子はローカル変数であり、
「i+数値」はそのビット数の整数を表現しています。&lt;/p&gt;

&lt;p&gt;また、declareでは@putsを外部関数として宣言しており、main内でそれを用いています。
getelementptrは配列や構造体からアドレスを取得するための命令であり、
この例では単に文字列の先頭のアドレスを得ているだけです。
具体的には、第1引数はベースとなるアドレス、
第2引数以降はインデックスを指定します。この例では
第2引数は[14 x i8]に、第3引数はi8に対するインデックスとなります。&lt;/p&gt;

&lt;p&gt;ここから、実行ファイルを作成して、実行するには次のようにします。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt; llc helloworld.ll &amp;amp;&amp;amp; gcc helloworld.s &amp;amp;&amp;amp; ./a.out
Hello world!
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;なお、.llからllvmのビットコード(bc)にして、それを用いて実行するには次のようにします。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt; llvm-as helloworld.ll &amp;amp;&amp;amp; lli helloworld.bc 
Hello world!
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;次の例ではループを利用して0から9までをprintfで表示します。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@MSG = internal constant [4 x i8] c"%d\0A\00"

declare i32 @printf(i8*, ...)

define i32 @main() {
head:
  %cast_msg = getelementptr [4 x i8]* @MSG, i32 0, i32 0
  %i = alloca i32
  store i32 0, i32* %i
  br label %loop

loop:
  %val = load i32* %i
  call i32 (i8*, ...)* @printf(i8* %cast_msg, i32 %val)
  %ival = add i32 %val, 1
  store i32 %ival, i32* %i
  %b = icmp sle i32 %ival, 9
  br i1 %b, label %loop, label %tail

tail:
  ret i32 0
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;LLVMのアセンブリコードは、「&lt;a href="http://ja.wikipedia.org/wiki/%E9%9D%99%E7%9A%84%E5%8D%98%E4%B8%80%E4%BB%A3%E5%85%A5"&gt;静的単一代入&lt;/a&gt;」
と呼ばれる形式であり、各変数に再代入ができない形式になっています。
そのため、alloc命令でスタック上に領域を確保し、
load命令とstore命令によって値を保存したり取り出したりしています。&lt;/p&gt;

&lt;p&gt;なお、loop:ラベルの直前に無意味なbr命令がありますが、
ラベルを付ける場所が関数の先頭かbr命令の直後だけのようなので、その制限回避のためです。&lt;/p&gt;

&lt;p&gt;ちなみに、上のプログラムはphi命令を利用するとより簡単に書くことができます。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@MSG = internal constant [4 x i8] c"%d\0A\00"

declare i32 @printf(i8*, ...)

define i32 @main() {
head:
  %cast_msg = getelementptr [4 x i8]* @MSG, i32 0, i32 0
  br label %loop

loop:
  %val = phi i32 [ 0, %head ], [ %nextval, %loop ]
  %nextval = add i32 %val, 1
  call i32 (i8*, ...)* @printf(i8* %cast_msg, i32 %val)
  %b = icmp sle i32 %nextval, 9
  br i1 %b, label %loop, label %tail

tail:
  ret i32 0
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;phi命令は「現在のブロックの直前のブロック」によって結果の値を変えることができる命令です。
上のプログラムでは、1回目にphi命令に来たときにはheadラベルから来ているので
%valに0が代入され、それ以降はtailラベルの直前のbr命令から来ており
結果的に直前のブロックがloopとなるため%valには%nextvalが代入されます。
phi命令の次の行では%valに1足した値を%nextvalに代入しているので、これによって値が変更されていきます。&lt;/p&gt;

&lt;p&gt;また (当然でしょうが)、ループのプログラムの例は出力される結果が異なります。ふたつめの例では、スタックを一時変数に用いずにレジスタだけを利用していることがわかります。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt; diff -u =(llc loop1.ll -o - -x86-asm-syntax=intel) =(llc loop2.ll -o - -x86-asm-syntax=intel)
--- /tmp/zshAjFUQG    2011-01-31 22:35:56.000000000 +0900
+++ /tmp/zshw9GEZr    2011-01-31 22:35:56.000000000 +0900
@@ -10,19 +10,17 @@
 Ltmp1:
     sub RSP, 8
 Ltmp2:
-    mov DWORD PTR [RSP + 4], 0
-    lea RBX, QWORD PTR [RIP + _MSG]
+    xor EBX, EBX
+    lea R14, QWORD PTR [RIP + _MSG]
     .align  4, 0x90
 LBB0_1:                                 ## %loop
                                         ## =&amp;gt;This Inner Loop Header: Depth=1
-    mov R14D, DWORD PTR [RSP + 4]
-    mov RDI, RBX
-    mov ESI, R14D
+    mov RDI, R14
+    mov ESI, EBX
     xor AL, AL
     call    _printf
-    inc R14D
-    mov DWORD PTR [RSP + 4], R14D
-    cmp R14D, 10
+    inc EBX
+    cmp EBX, 10
     jl  LBB0_1
 ## BB#2:                                ## %tail
     xor EAX, EAX
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;なお、llvm-gccにオプション--emit-llvmと-Sを付けることでC言語からLLVMのアセンブリコードを得ることができます。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;llvm-gcc foobar.c -o foobar.ll -S --emit-llvm
&lt;/code&gt;&lt;/pre&gt;

&lt;h4&gt;まとめ&lt;/h4&gt;

&lt;p&gt;LLVMのアセンブリコードによるプログラムを試してみました。&lt;/p&gt;

&lt;h4&gt;関連記事&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://llvm.org/docs/LangRef.html"&gt;LLVM Assembly Language Reference Manual&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://ja.wikipedia.org/wiki/%E9%9D%99%E7%9A%84%E5%8D%98%E4%B8%80%E4%BB%A3%E5%85%A5"&gt;静的単一代入 - Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://clang.llvm.org/"&gt;&amp;quot;clang&amp;quot; C Language Family Frontend for LLVM&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5191809332257264217-8469736744638779493?l=safx-dev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/4z5soXBn6tP5FllkLqY4bCf4tWU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/4z5soXBn6tP5FllkLqY4bCf4tWU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/4z5soXBn6tP5FllkLqY4bCf4tWU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/4z5soXBn6tP5FllkLqY4bCf4tWU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/TFCRl/~4/5IGSsjWZ1Vs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://safx-dev.blogspot.com/feeds/8469736744638779493/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://safx-dev.blogspot.com/2011/01/llvm.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/8469736744638779493?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/8469736744638779493?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/TFCRl/~3/5IGSsjWZ1Vs/llvm.html" title="LLVMのアセンブリコードによるプログラム" /><author><name>safx developer</name><uri>http://www.blogger.com/profile/13931453776402259724</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/-xmu-GKy-rZo/TY10GvG4LYI/AAAAAAAAAgo/2rul0qNef4Q/s220/%255Bsafx%255D%2B-%2B%25E3%2581%2595%25E3%2581%25B5%25E9%2596%258B%25E7%2599%25BA%25E8%2580%2585.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/_XbtP-rrPvTg/TUbF19FspNI/AAAAAAAAAZc/Cp61R2emm9g/s72-c/P1319752-3.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://safx-dev.blogspot.com/2011/01/llvm.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkQGRXozfSp7ImA9WhdWEEg.&quot;"><id>tag:blogger.com,1999:blog-5191809332257264217.post-1841543908181009815</id><published>2011-01-08T23:15:00.006+09:00</published><updated>2011-09-03T21:52:04.485+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-03T21:52:04.485+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="iPhone" /><category scheme="http://www.blogger.com/atom/ns#" term="Mac" /><category scheme="http://www.blogger.com/atom/ns#" term="Xcode" /><title>Xcode 3.2.5にiOS 4.0 SDKを導入する方法について</title><content type="html">&lt;p&gt;先日、Xcode 3.2.5をインストールしたところ、iOS 4.0のSDKが使用できなくなりました。いろいろ試したところ、古いXcodeのdmgからiOS 4.0のSDKを取ってきて利用することができましたので、その手順を紹介します。&lt;/p&gt;&lt;a href="http://picasaweb.google.com/lh/photo/QNIpgARpI-sCh0gBIG3B5A?feat=embedwebsite"&gt;&lt;img src="http://lh6.ggpht.com/_XbtP-rrPvTg/TSSAukb_jYI/AAAAAAAAAWQ/XahvWXWhUpA/s400/xc02.png" height="314" width="400" /&gt;&lt;/a&gt; &lt;a name='more'&gt;&lt;/a&gt;  &lt;h4&gt;Xcode 3.2.5のインストール&lt;/h4&gt;&lt;p&gt;まず、以前のバージョンのXcodeを導入しているならアンインストールします。dmg内にインストールパッケージとともに存在しているドキュメント「About Xcode and iPhone SDK」にも書かれていますが、ターミナルから次のようなコマンドを入力します。&lt;/p&gt;&lt;pre class="brush:bash"&gt;sudo /Developer/Library/uninstall-devtools --mode=all&lt;/pre&gt;&lt;p&gt;そして、Xcode 3.2.5をインストールします。&lt;/p&gt;&lt;h4&gt;古いiOS SDKのインストール&lt;/h4&gt;&lt;p&gt;まず、「&lt;a href="http://iphonesdkdev.blogspot.com/2010/04/old-versions-of-iphone-sdk.html"&gt;iPhone Software Development: Old versions of iPhone SDK&lt;/a&gt;」を参照して、Xcode 3.2.3のdmgを取得します。&lt;/p&gt;&lt;a href="http://picasaweb.google.com/lh/photo/WQeiIAcsmNKvB3xgfkwidQ?feat=embedwebsite"&gt;&lt;img src="http://lh4.ggpht.com/_XbtP-rrPvTg/TSSAufIuXVI/AAAAAAAAAWM/Zp-k47cOHPo/s800/xc01.png" height="154" width="373" /&gt;&lt;/a&gt;  &lt;p&gt;次に、ダウンロードしたdmgをマウントします。Finderが起動するかもしれませんが、パッケージを直接参照できないので閉じてください。そして、dmgをマウントしたままでターミナルを起動して次のように入力します。なお、シングルクォート内の内容はお使いの環境やマウントするdmgによって異なる可能性があります。&lt;/p&gt;&lt;pre class="brush:bash"&gt;open -a Finder '/Volumes/Xcode and iPhone SDK/Packages'&lt;/pre&gt;&lt;p&gt;すると、次のように沢山のパッケージがファインダーで表示されます。この中からiPhoneSDK4_0.pkgをダブルクリックしてインストールします。&lt;/p&gt;&lt;a href="http://picasaweb.google.com/lh/photo/QNIpgARpI-sCh0gBIG3B5A?feat=embedwebsite"&gt;&lt;img src="http://lh6.ggpht.com/_XbtP-rrPvTg/TSSAukb_jYI/AAAAAAAAAWQ/XahvWXWhUpA/s400/xc02.png" height="314" width="400" /&gt;&lt;/a&gt;  &lt;p&gt;ただし、そのままだとインストール先が正しくないため次のようにしてインストール先を/Developerにします。まず、インストールウィザード中の[Installation Type]で[Change Install Location...]をクリック。&lt;/p&gt;&lt;a href="http://picasaweb.google.com/lh/photo/Ulupu1oyyIpQEwgM8f3F1A?feat=embedwebsite"&gt;&lt;img src="http://lh5.ggpht.com/_XbtP-rrPvTg/TSSAukHWSAI/AAAAAAAAAWU/GQ02ZCFtnV0/s400/xc03.png" height="286" width="400" /&gt;&lt;/a&gt;  &lt;p&gt;[Developer]を指定して[Choose]してください。&lt;/p&gt;&lt;a href="http://picasaweb.google.com/lh/photo/mJBfCaxJTnRP5VZ_BEaf-w?feat=embedwebsite"&gt;&lt;img src="http://lh3.ggpht.com/_XbtP-rrPvTg/TSSAuwsTm9I/AAAAAAAAAWY/JVgAaZ3ecwE/s400/xc04.png" height="284" width="400" /&gt;&lt;/a&gt;  &lt;p&gt;インストール先が"Developer"になっていることを確認して、[Continue]をクリック。&lt;/p&gt;&lt;a href="http://picasaweb.google.com/lh/photo/u9985J-ZxHdgZMQ8YOf_fQ?feat=embedwebsite"&gt;&lt;img src="http://lh4.ggpht.com/_XbtP-rrPvTg/TSSAvMZHZcI/AAAAAAAAAWc/BtDy66F_9mo/s400/xc05.png" height="287" width="400" /&gt;&lt;/a&gt;  &lt;p&gt;以上で、/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.0.sdkにiOS 4.0のSDKがインストールされます。なお、Xcode 3.2.5にもiPhoneSDK4_0.pkgが存在していますが、Xcode 3.2.3に付属のものとは内容が異なるらしく、上記の手順では使用することはできませんでした。&lt;/p&gt;&lt;pre class="brush:bash"&gt;MD5 (/Volumes/Xcode and iOS SDK/Packages/iPhoneSDK4_0.pkg)    = a09986714b357dede884362997f76edf  # 3.2.5
MD5 (/Volumes/Xcode and iPhone SDK/Packages/iPhoneSDK4_0.pkg) = 1d4dd7957d932038e2f2b0b3e2a7f2f9  # 3.2.3 
&lt;/pre&gt;&lt;h4&gt;おまけ: iPhoneSDK4_0.pkgの中身&lt;/h4&gt;&lt;p&gt;pkgファイルの中身は次のようになっています。&lt;/p&gt;&lt;pre class="brush:bash"&gt;&amp;gt; xar -tvf /Volumes/Xcode\ and\ iOS\ SDK/Packages/iPhoneSDK4_0.pkg
-rw-r--r--      root/wheel        393048 2010-10-27 08:54:28 Bom
-rw-r--r--      root/wheel           536 2010-10-27 08:59:09 PackageInfo
-rw-r--r--      root/wheel     350292508 2010-10-27 08:54:14 Payload
&lt;/pre&gt;&lt;p&gt;これらのファイルは次のような形式のファイルです。&lt;/p&gt;&lt;pre class="brush:bash"&gt;&amp;gt; file *
Bom:          Mac OS X bill of materials (BOM) file
PackageInfo:  XML document text
Payload:      gzip compressed data, from Unix
&lt;/pre&gt;&lt;p&gt;ファイルPackageInfoは次のようなXMLファイルで、内容はよくわかりません。&lt;/p&gt;&lt;pre class="brush:bash"&gt;&amp;gt; lv PackageInfo # 3.2.5のiPhoneSDK4_0.pkg
&amp;lt;?xml version="1.0"?&amp;gt;
&amp;lt;pkg-info format-version="2" relocatable="true" deleteObsoleteLanguages="true" identifier="com.apple
.pkg.iPhoneSDK4_0" overwrite-permissions="yes" auth="root" postinstall-action="none" version="4.0.0.
9000000000.1.1206372128"&amp;gt;
  &amp;lt;payload installKBytes="847139" numberOfFiles="1249"/&amp;gt;
  &amp;lt;scripts/&amp;gt;
  &amp;lt;groups&amp;gt;
    &amp;lt;group&amp;gt;com.apple.FindSystemFiles.pkg-group&amp;lt;/group&amp;gt;
    &amp;lt;group&amp;gt;com.apple.DevToolsRelocatable.pkg-group&amp;lt;/group&amp;gt;
    &amp;lt;group&amp;gt;com.apple.iPhoneSDK.pkg-group&amp;lt;/group&amp;gt;
  &amp;lt;/groups&amp;gt;
  &amp;lt;bundle-version/&amp;gt;
&amp;lt;/pkg-info&amp;gt;
&lt;/pre&gt;&lt;p&gt;ファイルBomはファイル構成一覧を記述したファイルのようで、lsbomで内容を見ることができます。&lt;/p&gt;&lt;pre class="brush:bash"&gt;&amp;gt; lsbom Bom # 3.2.5のiPhoneSDK4_0.pkg
    :
./Platforms/iPhoneOS.platform/DeviceSupport/4.0/Symbols/usr    40775   0/80
./Platforms/iPhoneOS.platform/DeviceSupport/4.0/Symbols/usr/lib    40775   0/80
./Platforms/iPhoneOS.platform/DeviceSupport/4.0/Symbols/usr/lib/dyld    100775  0/80    476320  2618116526
./Platforms/iPhoneOS.platform/DeviceSupport/4.0/Symbols/usr/lib/gcc    40775   0/80
./Platforms/iPhoneOS.platform/DeviceSupport/4.0/Symbols/usr/lib/gcc/arm-apple-darwin10
    :
&lt;/pre&gt;&lt;p&gt;Xcode 3.2.3に付属のiPhoneSDK4_0.pkgは3.2.3のものとディレクトリ構成が異なっていたりplistがなかったりします。&lt;/p&gt;&lt;pre class="brush:bash"&gt;&amp;gt; lsbom Bom-3.2.3 | grep plist
./Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.0.sdk/Entitlements.plist    100644  0/0 423 4179759460
./Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.0.sdk/ResourceRules.plist    100644  0/0 485 3752781124
./Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.0.sdk/SDKSettings.plist    100644  0/0 1489    979933569

&amp;gt; lsbom Bom-3.2.5 | grep plist
zsh: done       lsbom Bom-3.2.5 | 
zsh: exit 1     grep plist
&lt;/pre&gt;&lt;h4&gt;まとめ&lt;/h4&gt;&lt;p&gt;Xcode 3.2.5にiOS 4.0 SDKを導入する方法を述べました。&lt;/p&gt;&lt;h4&gt;関連項目&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://iphonesdkdev.blogspot.com/2010/04/old-versions-of-iphone-sdk.html"&gt;iPhone Software Development: Old versions of iPhone SDK&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5191809332257264217-1841543908181009815?l=safx-dev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/NOGJOeC6LQQ0INPMx2Qxg8qK0jw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/NOGJOeC6LQQ0INPMx2Qxg8qK0jw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/NOGJOeC6LQQ0INPMx2Qxg8qK0jw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/NOGJOeC6LQQ0INPMx2Qxg8qK0jw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/TFCRl/~4/jIsDeI7SDlk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://safx-dev.blogspot.com/feeds/1841543908181009815/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://safx-dev.blogspot.com/2011/01/xcode-325ios-40-sdk.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/1841543908181009815?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/1841543908181009815?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/TFCRl/~3/jIsDeI7SDlk/xcode-325ios-40-sdk.html" title="Xcode 3.2.5にiOS 4.0 SDKを導入する方法について" /><author><name>safx developer</name><uri>http://www.blogger.com/profile/13931453776402259724</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/-xmu-GKy-rZo/TY10GvG4LYI/AAAAAAAAAgo/2rul0qNef4Q/s220/%255Bsafx%255D%2B-%2B%25E3%2581%2595%25E3%2581%25B5%25E9%2596%258B%25E7%2599%25BA%25E8%2580%2585.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/_XbtP-rrPvTg/TSSAukb_jYI/AAAAAAAAAWQ/XahvWXWhUpA/s72-c/xc02.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://safx-dev.blogspot.com/2011/01/xcode-325ios-40-sdk.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0ADR3ozfSp7ImA9Wx9bGU0.&quot;"><id>tag:blogger.com,1999:blog-5191809332257264217.post-7311378075573612685</id><published>2010-12-31T18:58:00.009+09:00</published><updated>2011-03-01T01:16:16.485+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-03-01T01:16:16.485+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="統計情報" /><title>2010年の人気記事一覧と統計情報</title><content type="html">&lt;a href="http://picasaweb.google.com/lh/photo/Qa-vKiU7KFukgxvaNs4WLg?feat=embedwebsite"&gt;&lt;img src="http://lh4.ggpht.com/_XbtP-rrPvTg/TPON_1nBt7I/AAAAAAAAAS4/UbG-AZ4qYMI/s400/P1308490.jpg" height="300" width="400" /&gt;&lt;/a&gt;
&lt;p&gt;2010年も最後の日になりましたので、2010年で本ブログの記事の中で人気のあったページや統計情報をまとめてみました。これらはBloggerの統計タブによる情報に基づいており、評価基準はページビューによるものです。&lt;/p&gt;
&lt;a name='more'&gt;&lt;/a&gt;
&lt;p&gt;人気のあったページは次の通りです。なお、1位の記事へのビュー数は全体の20%ほどを占めています。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;img class="none" src="http://lh4.ggpht.com/_XbtP-rrPvTg/THvcSWbrhqI/AAAAAAAAAFI/bz9ZDvB6juI/s72-c/dbox01.png" /&gt;
&lt;a href="http://safx-dev.blogspot.com/2010/08/dropbox-sdk-for-ios.html"&gt;Dropbox SDK for iOSのためのディベロッパキーの取得方法とサンプルアプリケーションのコンパイルについて&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;img class="none" src="http://lh3.ggpht.com/_XbtP-rrPvTg/TKWBAQRcnvI/AAAAAAAAALc/L1B7aPJyu1Q/s72-c/Screen%20shot%202010-09-30%20at%2019.56.57.png" /&gt;
&lt;a href="http://safx-dev.blogspot.com/2010/10/iosurl.html"&gt;iOSで独自カスタムURLスキームを設定する方法について&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;img class="none" src="http://lh5.ggpht.com/_XbtP-rrPvTg/TKRHn5ilGHI/AAAAAAAAAKg/vovcA7_ZrlQ/s72-c/urlscheme_sample.png" /&gt;
&lt;a href="http://safx-dev.blogspot.com/2010/09/iosurl.html"&gt;iOSでカスタムURLスキームを利用してアプリケーションを起動する方法について&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;img class="none" src="http://lh6.ggpht.com/_XbtP-rrPvTg/TKSdEyHWDEI/AAAAAAAAAK0/mhdVvQf2e0I/s72-c/ios_state.png" /&gt;
&lt;a href="http://safx-dev.blogspot.com/2010/09/ios-4.html"&gt;iOS 4のマルチタスク処理における状態遷移について&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;img class="none" src="http://lh6.ggpht.com/_XbtP-rrPvTg/TLhyt0cu3II/AAAAAAAAAOo/InCRLssARKw/s72-c/viewmanagement.png" /&gt;
&lt;a href="http://safx-dev.blogspot.com/2010/10/viewcontroller.html"&gt;ViewControllerにおけるビュー管理サイクルとメモリ警告シミュレーションによるアンロード処理について&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;img class="none" src="http://lh6.ggpht.com/_XbtP-rrPvTg/TOUO0P38ovI/AAAAAAAAASA/RhyOnZFNhf4/s72-c/q1a.png" /&gt;
&lt;a href="http://safx-dev.blogspot.com/2010/11/uidocumentinteractioncontroller.html"&gt;UIDocumentInteractionControllerを用いて別アプリケーションを開くメニューを表示する方法について&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;img class="none" src="http://lh4.ggpht.com/_XbtP-rrPvTg/THvABjP-KXI/AAAAAAAAAEw/qQmKfWqd7xM/s72-c/x09.png" /&gt;
&lt;a href="http://safx-dev.blogspot.com/2010/08/iphone.html"&gt;iPhoneでのサンプルアプリケーション作成&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;img class="none" src="http://lh6.ggpht.com/_XbtP-rrPvTg/THvcomachoI/AAAAAAAAAGE/492_69AZ92A/s72-c/dbox17.jpg" /&gt;
&lt;a href="http://safx-dev.blogspot.com/2010/09/iphonedropbox-sdk.html"&gt;Dropbox SDKを利用したiPhoneアプリケーションの作成&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;img class="none" src="http://lh3.ggpht.com/_XbtP-rrPvTg/TNkL2CVt0vI/AAAAAAAAARM/86J2qHI5jIU/s72-c/PA036663.jpg" /&gt;
&lt;a href="http://safx-dev.blogspot.com/2010/11/nsurlconnectionurl.html"&gt;NSURLConnectionを用いたURLローディングシステムによる通信&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;img class="none" src="http://lh4.ggpht.com/_XbtP-rrPvTg/TK7SUApxWnI/AAAAAAAAAMs/rITf_laDM3o/s72-c/atok01.jpg" /&gt;
&lt;a href="http://safx-dev.blogspot.com/2010/10/urlatok-pad-for-iphone.html"&gt;カスタムURLスキームと名前付きペーストボードを利用したATOK Pad for iPhoneとの連携&lt;/a&gt;
&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;ページビュー数の月ごとの遷移は次のようになりました。本格的に記事を書き始めたのが9月ごろで、それ以降は月間約2000ページビューくらいで推移しており、年間では約9000ページビュー程度でした。&lt;/p&gt;
&lt;img src="http://lh5.ggpht.com/_XbtP-rrPvTg/TR2iinw9IJI/AAAAAAAAAV4/F942XobbUdg/s500/a000.png" /&gt;

&lt;p&gt;ページビューのブラウザ別の割合は次のようになりました。1%未満のものにはOpera, OneRiot, Jakarta Commons-HttpClientなどがありました。&lt;/p&gt;
&lt;img class="none" src="http://lh6.ggpht.com/_XbtP-rrPvTg/TR2ci3pZ2VI/AAAAAAAAAVo/aTT5fwfAV7E/s800/a002.png" /&gt;
&lt;table class="mytable"&gt;
&lt;tr&gt;&lt;th&gt;ブラウザ&lt;/th&gt;&lt;th&gt;割合&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Firefox&lt;/td&gt;&lt;td&gt;31%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Safari&lt;/td&gt;&lt;td&gt;27%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Chrome&lt;/td&gt;&lt;td&gt;23%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Internet Explorer&lt;/td&gt;&lt;td&gt;12%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Mobile&lt;/td&gt;&lt;td&gt;2%&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;ページビューのOS別の割合は次の通りです。やはりMacが多いです。なお、1%未満のものにはiPad, iPod, Linuxなどがありました。&lt;/p&gt;
&lt;img class="none" src="http://lh4.ggpht.com/_XbtP-rrPvTg/TR2ci_Tb6ZI/AAAAAAAAAVs/z2n2-Ey_nLA/s800/a003.png" /&gt;
&lt;table class="mytable"&gt;
&lt;tr&gt;&lt;th&gt;OS&lt;/th&gt;&lt;th&gt;割合&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Macintosh&lt;/td&gt;&lt;td&gt;52%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Windows&lt;/td&gt;&lt;td&gt;37%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;iPhone&lt;/td&gt;&lt;td&gt;6%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Other Unix&lt;/td&gt;&lt;td&gt;2%&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;今現在iOS開発関連で書くことがないため、来年はブログの更新頻度が落ちると思います。
また、iOS以外の記事が増えていくかもしれませんが、引き続きプログラム関連の記事をメインにしていくつもりです。&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5191809332257264217-7311378075573612685?l=safx-dev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/1Y_E4z-b-wY1jg81W8YWwGS16WM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/1Y_E4z-b-wY1jg81W8YWwGS16WM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/1Y_E4z-b-wY1jg81W8YWwGS16WM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/1Y_E4z-b-wY1jg81W8YWwGS16WM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/TFCRl/~4/S19BWxHRo9c" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://safx-dev.blogspot.com/feeds/7311378075573612685/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://safx-dev.blogspot.com/2010/12/2010.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/7311378075573612685?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/7311378075573612685?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/TFCRl/~3/S19BWxHRo9c/2010.html" title="2010年の人気記事一覧と統計情報" /><author><name>safx developer</name><uri>http://www.blogger.com/profile/13931453776402259724</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/-xmu-GKy-rZo/TY10GvG4LYI/AAAAAAAAAgo/2rul0qNef4Q/s220/%255Bsafx%255D%2B-%2B%25E3%2581%2595%25E3%2581%25B5%25E9%2596%258B%25E7%2599%25BA%25E8%2580%2585.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/_XbtP-rrPvTg/TPON_1nBt7I/AAAAAAAAAS4/UbG-AZ4qYMI/s72-c/P1308490.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://safx-dev.blogspot.com/2010/12/2010.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkcBR30zfCp7ImA9Wx9QF00.&quot;"><id>tag:blogger.com,1999:blog-5191809332257264217.post-5176153063407461227</id><published>2010-12-21T21:23:00.009+09:00</published><updated>2010-12-30T19:14:16.384+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-12-30T19:14:16.384+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="UIDocumentInteractionController" /><category scheme="http://www.blogger.com/atom/ns#" term="ライブラリ" /><category scheme="http://www.blogger.com/atom/ns#" term="iPhone" /><category scheme="http://www.blogger.com/atom/ns#" term="クイックルック" /><title>UIDocumentInteractionControllerDelegateの処理の流れについて</title><content type="html">&lt;p&gt;以前の記事「&lt;a href="http://safx-dev.blogspot.com/2010/11/uidocumentinteractioncontroller.html"&gt;さふ開発日記: UIDocumentInteractionControllerを用いて別アプリケーションを開くメニューを表示する方法について&lt;/a&gt;」において、解放周りのコードが間違えていたようなので訂正を兼ねてDocumentInteractionControllerDelegateの処理の流れを調べてみました。&lt;/p&gt;

&lt;a href="http://picasaweb.google.com/lh/photo/g76QV44dfoLXILnDjjo1Eg?feat=embedwebsite"&gt;&lt;img src="http://lh4.ggpht.com/_XbtP-rrPvTg/TRxbDpZ5UdI/AAAAAAAAAVc/ydEMbYcEaQQ/s800/dicflow.png" height="743" width="521" /&gt;&lt;/a&gt;
&lt;a name='more'&gt;&lt;/a&gt;

&lt;p&gt;上図はUIDocumentInteractionControllerにおいて、presentOptionsMenuFromRect:inView:animated:を呼び出したときの処理の流れになります。丸四角が呼び出されるデリゲートメソッド、四角がウィジェット状態の変化を示しています。なお、メソッド名があまりにも長いため、最初のdocumentInteractionControllerを「DIC」と省略しています。また、緑文字はオプションメニューでタップしたボタンがどれかということを示しており、その個所がユーザの入力待ちになることを意味します。そして、点線はクイックルックが表示されていることを示しています。&lt;/p&gt;

&lt;p&gt;ここで、オプションメニューとクイックルックとはそれぞれ次のようなものであるとします。&lt;/p&gt;
&lt;a href="http://picasaweb.google.com/lh/photo/CIKx21f4H6PsWZimE9h7cg?feat=embedwebsite"&gt;&lt;img src="http://lh6.ggpht.com/_XbtP-rrPvTg/TRCXh0kC_xI/AAAAAAAAAUs/BEFVczZ_GfM/s192/q1a.png" height="156" width="192" /&gt;&lt;/a&gt; &lt;a href="http://picasaweb.google.com/lh/photo/q6E2DpP7xpU-HHh31YzBEw?feat=embedwebsite"&gt;&lt;img src="http://lh6.ggpht.com/_XbtP-rrPvTg/TOUO0WT7ocI/AAAAAAAAASE/JTcFpXH_krY/s288/q2.png" height="288" width="192" /&gt;&lt;/a&gt;

&lt;p&gt;以前のコードだと、presentOptionsMenuFromRect:inView:animated:の直後にretainして、documentInteractionControllerDidEndPreview:内でautoreleaseをしていたのですが、これだとクイックビュー以外ではコントローラが解放されなくなってしまいます。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;2010.12.30追記: 上図の「 別アプリを選択」のフローが間違っていたので訂正しました (&lt;a href="http://picasaweb.google.com/lh/photo/aXOnIFyefPlwtFvVA3lyCA?feat=embedwebsite"&gt;以前の図&lt;/a&gt;)。また、それに伴ない、次の記述は誤りになります。親クラスで管理するのが最良の方法のようです。&lt;/p&gt;
&lt;p&gt;そのため、上図において+1の個所でretain、−1の個所でautoreleaseするのがよいようです (presentOptionsMenuFromRect:inView:animated:とDocumentInteractionControllerDidMismissOptionMenu:の組み合わせのみだとクイックルックを選択した場合Abortしてしまう)。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;まとめ&lt;/h4&gt;
&lt;p&gt;DocumentInteractionControllerDelegateの処理の流れについて述べました。&lt;/p&gt;

&lt;h4&gt;関連項目&lt;/h4&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://safx-dev.blogspot.com/2010/11/uidocumentinteractioncontroller.html"&gt;さふ開発日記: UIDocumentInteractionControllerを用いて別アプリケーションを開くメニューを表示する方法について&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://safx-dev.blogspot.com/2010/12/quick-look-framework%E3%82%92%E7%94%A8%E3%81%84%E3%81%9F%E3%83%97%E3%83%AC%E3%83%93%E3%83%A5%E3%83%BC%E8%A1%A8%E7%A4%BA%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6.html?utm_source=BP_recent"&gt;さふ開発日記: Quick Look Frameworkを用いたプレビュー表示について&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://developer.apple.com/library/ios/#documentation/uikit/reference/UIDocumentInteractionControllerDelegate_protocol/Reference/Reference.html#//apple_ref/doc/uid/TP40009305"&gt;UIDocumentInteractionControllerDelegate Protocol Reference Protocol Reference&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5191809332257264217-5176153063407461227?l=safx-dev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/OxPOCqpj98NKuxL4_Daj6X254rk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/OxPOCqpj98NKuxL4_Daj6X254rk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/OxPOCqpj98NKuxL4_Daj6X254rk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/OxPOCqpj98NKuxL4_Daj6X254rk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/TFCRl/~4/34SYtWLNN60" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://safx-dev.blogspot.com/feeds/5176153063407461227/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://safx-dev.blogspot.com/2010/12/uidocumentinteractioncontrollerdelegate.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/5176153063407461227?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/5176153063407461227?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/TFCRl/~3/34SYtWLNN60/uidocumentinteractioncontrollerdelegate.html" title="UIDocumentInteractionControllerDelegateの処理の流れについて" /><author><name>safx developer</name><uri>http://www.blogger.com/profile/13931453776402259724</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/-xmu-GKy-rZo/TY10GvG4LYI/AAAAAAAAAgo/2rul0qNef4Q/s220/%255Bsafx%255D%2B-%2B%25E3%2581%2595%25E3%2581%25B5%25E9%2596%258B%25E7%2599%25BA%25E8%2580%2585.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/_XbtP-rrPvTg/TRxbDpZ5UdI/AAAAAAAAAVc/ydEMbYcEaQQ/s72-c/dicflow.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://safx-dev.blogspot.com/2010/12/uidocumentinteractioncontrollerdelegate.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEEDQ34ycSp7ImA9WhdWEEg.&quot;"><id>tag:blogger.com,1999:blog-5191809332257264217.post-5259529352485682491</id><published>2010-12-14T20:10:00.008+09:00</published><updated>2011-09-03T21:24:32.099+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-03T21:24:32.099+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="統一型識別子" /><category scheme="http://www.blogger.com/atom/ns#" term="UTI" /><category scheme="http://www.blogger.com/atom/ns#" term="ライブラリ" /><category scheme="http://www.blogger.com/atom/ns#" term="iPhone" /><category scheme="http://www.blogger.com/atom/ns#" term="クイックルック" /><title>Quick Look Frameworkを用いたプレビュー表示について</title><content type="html">&lt;p&gt;以前の記事「&lt;a href="http://safx-dev.blogspot.com/2010/11/uidocumentinteractioncontroller.html"&gt;UIDocumentInteractionControllerを用いて別アプリケーションを開くメニューを表示する方法について&lt;/a&gt;」ではアクションシートやクイックルックを表示する方法を紹介しました。クイックルックの実装クラスであるQLPreviewControllerはクイックルックと同じプレビューや他アプリケーションへの転送機能を持っており、さらにプレビュー対象を複数項目にすると、項目間のナビゲーションを行う矢印が付きます (ただし、モーダルビューのとき)。また、データソースがデリゲートになっているので、ナビゲーションによる移動後にオンデマンドでデータの作成や取得を行うことができます。&lt;/p&gt;&lt;p&gt;本記事ではiOS4.0上で、クイックルックのクラスQLPreviewControllerを利用したプレビューを表示する方法について紹介します。詳細はAppleのドキュメント「Document Interaction Programming Topics for iOS」の&lt;a href="http://developer.apple.com/library/ios/#documentation/FileManagement/Conceptual/DocumentInteraction_TopicsForIOS/Articles/UsingtheQuickLookFramework.html#//apple_ref/doc/uid/TP40010413-SW1"&gt;Using the Quick Look Framework&lt;/a&gt;を参照してください。&lt;/p&gt;&lt;a href="http://picasaweb.google.com/lh/photo/pYs_1u6Y2YclfIAH_-SCmA?feat=embedwebsite"&gt;&lt;img src="http://lh5.ggpht.com/_XbtP-rrPvTg/TQdP-pVnbHI/AAAAAAAAATw/xmBLwc49Ntc/s400/ishot-5.png" height="400" width="267" /&gt;&lt;/a&gt; &lt;a name='more'&gt;&lt;/a&gt;  &lt;h4&gt;クイックルックの表示&lt;/h4&gt;&lt;p&gt;QLPreviewControllerはUIViewControllerのサブクラスであるため、ナビゲーションコントローラにpushすることもできますが、クイックルックのように、モーダルにして全画面表示にすると項目間のナビゲーションを行う矢印が付きます。具体的には次のコードのようになります。&lt;/p&gt;&lt;pre class="brush:cpp"&gt;QLPreviewController* ql = [[QLPreviewController alloc] init];
[self.navigationController presentModalViewController:ql animated:YES];
ql.dataSource = self;
[ql refreshCurrentPreviewItem];
&lt;/pre&gt;&lt;p&gt;なお、QuickLook/QuickLook.hをインポートして、フレームワークQuickLook.frameworkを追加する必要があります。また、delegateはQLPreviewControllerを閉じるときとプレビュー内でリンクをクリックしたときの挙動をカスタマイズするだけですので、今回は省略しています。&lt;/p&gt;&lt;h4&gt;データソースの実装&lt;/h4&gt;&lt;p&gt;データソースのためのプロトコルQLPreviewControllerDataSourceには2つの必須メソッド&lt;code&gt;numberOfPreviewItemsInPreviewController:&lt;/code&gt;と&lt;code&gt;previewController:previewItemAtIndex:&lt;/code&gt;があります。前者は表示項目数、後者は表示項目のURLとタイトルを示すQLPreviewItemを返すメソッドであり、コードは次のようになります。 &lt;/p&gt;&lt;pre class="brush:cpp"&gt;- (NSInteger)numberOfPreviewItemsInPreviewController:(QLPreviewController*)controller {
    return [previewItems count];
}

- (id&amp;lt;QLPreviewItem&amp;gt;)previewController:(QLPreviewController*)controller previewItemAtIndex:(NSInteger)index {
    FileInZipInfo* info = [previewItems objectAtIndex:index];
    NSString* path = [self extractFile:info];
    PreviewItem* item = [[PreviewItem alloc] initWithURL:[NSURL fileURLWithPath:path]];
    return [item autorelease];
}
&lt;/pre&gt;&lt;p&gt;上記のコードはZip内のファイルを必要になったときに解凍して表示させるコードになっています。ここで、extractFile:はZip内のファイルを解凍するメソッドとします。基本的には以前の記事「&lt;a href="http://safx-dev.blogspot.com/2010/12/objective-zipzip.html"&gt;さふ開発日記: Objective-Zipを用いたZip書庫の操作について&lt;/a&gt;」を参照に実装可能ですので、ここでは省略しています。また、PreviewItemは単純にプロトコルQLPreviewItemを実装しているだけですので、これも省略しています。&lt;/p&gt;&lt;h4&gt;QLPreviewControllerで表示可能な形式&lt;/h4&gt;&lt;p&gt;QLPreviewControllerは次の形式を表示可能です。これは、おそらくクイックルックと同じでしょう。&lt;/p&gt;&lt;ul&gt;&lt;li&gt;iWork documents&lt;/li&gt;
&lt;li&gt;Microsoft Office文書&lt;/li&gt;
&lt;li&gt;リッチテキスト&lt;/li&gt;
&lt;li&gt;PDF&lt;/li&gt;
&lt;li&gt;画像&lt;/li&gt;
&lt;li&gt;統一型識別子 (UTI) の public.text にあたるもの&lt;/li&gt;
&lt;li&gt;CSV&lt;/li&gt;
&lt;/ul&gt;&lt;h4&gt;まとめ&lt;/h4&gt;&lt;p&gt;クイックルックのクラスQLPreviewControllerを利用したプレビューを表示する方法について紹介しました。&lt;/p&gt;&lt;h4&gt;関連項目&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://safx-dev.blogspot.com/2010/12/objective-zipzip.html"&gt;さふ開発日記: Objective-Zipを用いたZip書庫の操作について&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://safx-dev.blogspot.com/2010/11/uidocumentinteractioncontroller.html"&gt;さふ開発日記: UIDocumentInteractionControllerを用いて別アプリケーションを開くメニューを表示する方法について&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://safx-dev.blogspot.com/2010/11/ios_21.html"&gt;さふ開発日記: iOSアプリケーションを特定のファイル形式に対応させる方法について&lt;/a&gt; 統一型識別子 (UTI) についてはこちらも参照してください&lt;/li&gt;
&lt;li&gt;&lt;a href="http://developer.apple.com/library/ios/#documentation/FileManagement/Conceptual/DocumentInteraction_TopicsForIOS/Articles/UsingtheQuickLookFramework.html#//apple_ref/doc/uid/TP40010413-SW1"&gt;Using the Quick Look Framework&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://developer.apple.com/library/ios/#documentation/NetworkingInternet/Reference/QLPreviewController_Class/Reference/Reference.html#//apple_ref/occ/cl/QLPreviewController"&gt;QLPreviewController Class Reference&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5191809332257264217-5259529352485682491?l=safx-dev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/uxdarUwDtrzcpemTcNyTORxzWc8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/uxdarUwDtrzcpemTcNyTORxzWc8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/uxdarUwDtrzcpemTcNyTORxzWc8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/uxdarUwDtrzcpemTcNyTORxzWc8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/TFCRl/~4/q6NYMrdhcwA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://safx-dev.blogspot.com/feeds/5259529352485682491/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://safx-dev.blogspot.com/2010/12/quick-look-framework%E3%82%92%E7%94%A8%E3%81%84%E3%81%9F%E3%83%97%E3%83%AC%E3%83%93%E3%83%A5%E3%83%BC%E8%A1%A8%E7%A4%BA%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/5259529352485682491?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/5259529352485682491?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/TFCRl/~3/q6NYMrdhcwA/quick-look-framework%E3%82%92%E7%94%A8%E3%81%84%E3%81%9F%E3%83%97%E3%83%AC%E3%83%93%E3%83%A5%E3%83%BC%E8%A1%A8%E7%A4%BA%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6.html" title="Quick Look Frameworkを用いたプレビュー表示について" /><author><name>safx developer</name><uri>http://www.blogger.com/profile/13931453776402259724</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/-xmu-GKy-rZo/TY10GvG4LYI/AAAAAAAAAgo/2rul0qNef4Q/s220/%255Bsafx%255D%2B-%2B%25E3%2581%2595%25E3%2581%25B5%25E9%2596%258B%25E7%2599%25BA%25E8%2580%2585.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh5.ggpht.com/_XbtP-rrPvTg/TQdP-pVnbHI/AAAAAAAAATw/xmBLwc49Ntc/s72-c/ishot-5.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://safx-dev.blogspot.com/2010/12/quick-look-framework%E3%82%92%E7%94%A8%E3%81%84%E3%81%9F%E3%83%97%E3%83%AC%E3%83%93%E3%83%A5%E3%83%BC%E8%A1%A8%E7%A4%BA%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEAGSHgyfCp7ImA9WhdWEEg.&quot;"><id>tag:blogger.com,1999:blog-5191809332257264217.post-3435952471794592084</id><published>2010-12-09T19:36:00.006+09:00</published><updated>2011-09-03T21:25:29.694+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-03T21:25:29.694+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ライブラリ" /><category scheme="http://www.blogger.com/atom/ns#" term="iPhone" /><category scheme="http://www.blogger.com/atom/ns#" term="Zip" /><title>Objective-Zipを用いたZip書庫の操作について</title><content type="html">&lt;p&gt;&lt;a href="http://code.google.com/p/objective-zip/"&gt;Objective-Zip&lt;/a&gt;は、現在最も普及しているであろう圧縮形式であるZipの圧縮と解凍を行うことができるObjective-Cのライブラリであり、&lt;a href="http://www.zlib.net/"&gt;ZLib&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;
と&lt;a href="http://www.winimage.com/zLibDll/minizip.html"&gt;Minizip&lt;/a&gt;という2つのライブラリを用いています。そのため、Objective-Zip自体は新BSDライセンスですが、ZLibとMiniZipはライセンスが異なる (zlibライセンス) ので注意してください。&lt;/p&gt;&lt;p&gt;Objective-Zipの現時点での最新バージョンである0.7.2は、iOSのバージョン3.1.2から4.2で利用可能です。この記事ではObjective-Zipを用いたZipファイルの操作を簡単に説明します。&lt;/p&gt;&lt;a href="http://picasaweb.google.com/lh/photo/PeJ13zL49aCU1P3ZTGGg4w?feat=embedwebsite"&gt;&lt;img src="http://lh3.ggpht.com/_XbtP-rrPvTg/TQCx3wN755I/AAAAAAAAATM/fg667TE3fB0/s400/PC099380.jpg" height="300" width="400" /&gt;&lt;/a&gt; &lt;a name='more'&gt;&lt;/a&gt; &lt;h4&gt;事前準備&lt;/h4&gt;&lt;p&gt;Xcodeで次の手順を行います。ちなみに、手元の環境ではzlibのライブラリは不要でした。なお、Minizipはzlibを利用してZipファイルの圧縮と解凍を行うライブラリです (zlibはgzipファイルを解凍できるが、zipファイルには対応していない)。&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Objective-Zip-0.7.2.zipをダウンロード&lt;/li&gt;
&lt;li&gt;Objective-Zip-0.7.2.zipを解凍し、MiniZipとObjective-ZipをDocumentsフォルダに移動&lt;/li&gt;
&lt;li&gt;[Add]→[Existing Files...]でMiniZipとObjective-Zipを追加&lt;/li&gt;
&lt;li&gt;[Add]→[Existing Frameworks...]でlibz*.dylibを追加 (libz.1.2.3.dylibのみを追加した)&lt;/li&gt;
&lt;/ol&gt;&lt;h4&gt;ファイル一覧表示&lt;/h4&gt;&lt;p&gt;Zipファイル内の一覧を表示するコードを次に示します。&lt;/p&gt;&lt;pre class="brush:cpp"&gt;ZipFile* zip = [[ZipFile alloc] initWithFileName:zipfilePath mode:ZipFileModeUnzip];
NSArray* array = [zip listFileInZipInfos];
for (FileInZipInfo* i in array) {
    NSLog(@"%@ %@", i.name, i.length);
}
[zip close];
[zip release];&lt;/pre&gt;&lt;h4&gt;ファイル解凍&lt;/h4&gt;&lt;p&gt;Zipファイル内から指定したファイルをひとつ解凍するコードを次に示します。zipInfo.sizeは圧縮時のサイズなので間違えないようにしてください。また、全部解凍するときはgoToNextFileInZipを利用したほうがよいでしょう。&lt;/p&gt;&lt;pre class="brush:cpp"&gt;ZipFile* zip = [[ZipFile alloc] initWithFileName:zipfilePath mode:ZipFileModeUnzip];
if ([zip locateFileInZip:zipInfo.name]) {
    ZipReadStream* read = [zip readCurrentFileInZip];
    NSMutableData* data = [[NSMutableData alloc] initWithLength:zipInfo.length];
    if ([read readDataWithBuffer:data]) {
       [data writeToFile:outputPath atomically:YES];
    }
    [read finishedReading];
    [data release];
}
[zip close];
[zip release];&lt;/pre&gt;&lt;h4&gt;ファイル圧縮&lt;/h4&gt;&lt;p&gt;Zipファイルを作成し、ファイルをひとつ追加するコードを次に示します。複数のファイルを追加する場合には余分にインデントしている4行の部分を繰り返します。なお、closeを忘れると書庫が壊れてしまうようですので注意してください。&lt;/p&gt;&lt;pre class="brush:cpp"&gt;ZipFile* zip = [[ZipFile alloc] initWithFileName:zipfilePath mode:ZipFileModeCreate];
    ZipWriteStream* write = [zip writeFileInZipWithName:[path lastPathComponent]
                                 compressionLevel:ZipCompressionLevelBest];
    NSData* data = [NSData dataWithContentsOfFile:path];
    [write writeData:data];
    [write finishedWriting];
[zip close];
[zip release];&lt;/pre&gt;&lt;h4&gt;おわりに&lt;/h4&gt;&lt;p&gt;Objective-Zipを用いたZipファイルの操作を説明しました。&lt;/p&gt;&lt;h4&gt;関連項目&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/objective-zip/"&gt;Objective-Zip - Project Hosting on Google Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.zlib.net/"&gt;zlib Home Site&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.winimage.com/zLibDll/minizip.html"&gt;Minizip: Zip and UnZip additionnal library&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5191809332257264217-3435952471794592084?l=safx-dev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/xRXpaPh9bk674EL0TFn9u6OpMg8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/xRXpaPh9bk674EL0TFn9u6OpMg8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/xRXpaPh9bk674EL0TFn9u6OpMg8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/xRXpaPh9bk674EL0TFn9u6OpMg8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/TFCRl/~4/iEmXzzQ_vKM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://safx-dev.blogspot.com/feeds/3435952471794592084/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://safx-dev.blogspot.com/2010/12/objective-zipzip.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/3435952471794592084?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/3435952471794592084?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/TFCRl/~3/iEmXzzQ_vKM/objective-zipzip.html" title="Objective-Zipを用いたZip書庫の操作について" /><author><name>safx developer</name><uri>http://www.blogger.com/profile/13931453776402259724</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/-xmu-GKy-rZo/TY10GvG4LYI/AAAAAAAAAgo/2rul0qNef4Q/s220/%255Bsafx%255D%2B-%2B%25E3%2581%2595%25E3%2581%25B5%25E9%2596%258B%25E7%2599%25BA%25E8%2580%2585.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/_XbtP-rrPvTg/TQCx3wN755I/AAAAAAAAATM/fg667TE3fB0/s72-c/PC099380.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://safx-dev.blogspot.com/2010/12/objective-zipzip.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEAMSHw5eyp7ImA9WhdWEEg.&quot;"><id>tag:blogger.com,1999:blog-5191809332257264217.post-8996313170141753005</id><published>2010-11-29T20:09:00.008+09:00</published><updated>2011-09-03T21:26:29.223+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-03T21:26:29.223+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="高階関数" /><category scheme="http://www.blogger.com/atom/ns#" term="Blocks" /><category scheme="http://www.blogger.com/atom/ns#" term="iPhone" /><category scheme="http://www.blogger.com/atom/ns#" term="GCD" /><title>Objective-C上でブロックオブジェクトによる高階関数を用いてソートする方法について</title><content type="html">&lt;a href="http://picasaweb.google.com/lh/photo/_MhxUilldMOBNQM2QH8bQg?feat=embedwebsite"&gt;&lt;img src="http://lh6.ggpht.com/_XbtP-rrPvTg/TPON_uks0ZI/AAAAAAAAAS0/SY9W84Zdp9I/s400/P5104022.jpg" height="300" width="400" /&gt;&lt;/a&gt; &lt;p&gt;iOS 4.0以降 (Mac OS Xなら10.6以降) で利用可能になったブロックオブジェクトは他の言語でのクロージャに相当するものです。ブロックオブジェクトはC, C++, Objective-Cで利用可能であり、Appleの並列実行アーキテクチャ&lt;a href="http://en.wikipedia.org/wiki/Grand_Central_Dispatch"&gt;Grand Central Dispatch&lt;/a&gt;における基盤要素にもなっています。&lt;/p&gt;&lt;p&gt;ブロックオブジェクトはスタック上に生成されるため、copyによってヒープに移動させて破棄されないようにする必要があります (そして、使用後に破棄されるようにするためにautoreleaseさせる必要があります)。しかし、その点に注意さえすれば戻り値をブロックオブジェクトにした&lt;a href="http://ja.wikipedia.org/wiki/%E9%AB%98%E9%9A%8E%E9%96%A2%E6%95%B0"&gt;高階関数&lt;/a&gt;を利用することができます。&lt;/p&gt;&lt;p&gt;この記事ではObjective-Cにおいて、ブロックオブジェクトで高階関数を用いることで比較用のブロックオブジェクトを作成し、それを用いてオブジェクトのソートを行う方法を紹介します。&lt;/p&gt;&lt;a name='more'&gt;&lt;/a&gt; &lt;h4&gt;ブロックオブジェクトの概要&lt;/h4&gt;&lt;p&gt;次のインタフェースを持つクラスFileがあり、その配列Arrayがあるとします。&lt;/p&gt;&lt;pre class="brush:cpp"&gt;@interface File { /* ... */ }
@property NSString* name;
@property BOOL isDirectory;
@property long size
@end&lt;/pre&gt;&lt;p&gt;この配列をnameでソートするときに、比較のためにブロックオブジェクト (以下、単にブロックとする) を利用するならsortedArrayUsingComparator:を使うことになります。ブロックはサーカムフレックス ^ で始まり、引数と本体がその後に続きます。&lt;/p&gt;&lt;pre class="brush:cpp"&gt;NSComparator comp = ^(id a, id b) {
    return [[a name] compare:[b name]];
}
NSArray* sortedArray = [array sortedArrayUsingComparator:comp];&lt;/pre&gt;&lt;p&gt;ここで、NSComparatorは次のようにtypedefされています。&lt;/p&gt;&lt;pre&gt;&lt;code&gt;typedef NSComparisonResult (^NSComparator)(id obj1, id obj2);&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;高階関数&lt;/h4&gt;&lt;p&gt;ここでは、高階関数を関数 (ブロック) を返す関数という意味で用いています。よくある単純な利用例としては次のようになります。&lt;/p&gt;&lt;pre class="brush:cpp"&gt;typedef int (^mulBlock)(int);

mulBlock makeMul(int x) {
    return [[ ^(int y) {
        return x * y;
    } copy] autorelease];
}

int main() {
    mulBlock mul5 = makeMul(5);
    printf("%d\n", mul5(4)); // 20
}&lt;/pre&gt;&lt;h4&gt;ファイルソートの問題&lt;/h4&gt;&lt;p&gt;ファイルをソートする際に問題となるのは、そのソート種類の豊富さです。ソート基準としてファイル名、ファイルサイズ、拡張子、更新日などがあり、それ以外にも次のようなものも考慮する必要があります。&lt;/p&gt;&lt;ul&gt;&lt;li&gt;拡張子や更新日などが一致するときには別の基準 (ファイル名など) でソートする&lt;/li&gt;
&lt;li&gt;ファイル名で、アルファベットの大文字と小文字を区別するのか&lt;/li&gt;
&lt;li&gt;フォルダとファイルを一緒にしてソートするのかどうか&lt;/li&gt;
&lt;li&gt;ソートの昇順、降順&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;a href="http://ja.wikipedia.org/wiki/%E5%AE%89%E5%AE%9A%E3%82%BD%E3%83%BC%E3%83%88"&gt;安定なソート&lt;/a&gt;を用いて、これらの基準を用いて順番にソートする方法もありますが、複数回ソートする必要があります。&lt;/p&gt;&lt;h4&gt;ファイルソートにおける高階関数の利用&lt;/h4&gt;&lt;p&gt;ある基準で比較し、同値になった場合は下位の基準としてNSComparator型のブロックfを用いるようなブロックを作成する関数を用意します。ここでは、ファイル名の比較 (compByName, compByIName) はベースレベルとしており、ブロックを返す関数にはしていません。&lt;/p&gt;&lt;pre class="brush:cpp"&gt;NSComparisonResult (^compByName)(id, id) = ^(id a, id b) {
    return [[a name] compare:[b name]];
};

NSComparisonResult (^compByIName)(id, id) = ^(id a, id b) {
    return [[a name] caseInsensitiveCompare:[b name]];
};

NSComparator makeCompByDir(NSComparator f) {
     return [[ ^(id a, id b) {
        BOOL adir = [a isDirectory];
        BOOL bdir = [b isDirectory];
        if (adir == bdir) return f(a, b);
        return (adir &amp;amp;&amp;amp; ! bdir)? NSOrderedAscending : NSOrderedDescending;
    } copy] autorelease];    
}

NSComparator makeCompBySize(NSComparator f) {
     return [[ ^(id a, id b) {
        long av = [a size];
        long bv = [b size];
        if (av == bv) return f(a, b);
        return av &amp;lt; bv? NSOrderedAscending : NSOrderedDescending;
    } copy] autorelease];
}

NSComparator makeCompByKind(NSComparator f) {
     return [[ ^(id a, id b) {
        NSComparisonResult res = [[a name].pathExtension 
           caseInsensitiveCompare:[b name].pathExtension];
        return res == NSOrderedSame? f(a, b) : res;
    } copy] autorelease];    
}&lt;/pre&gt;&lt;p&gt;これらを用いて、(1) フォルダとファイルを別にして、(2) 拡張子でソートし、(3) 同一拡張子内はファイル名でソート (大文字と小文字を区別) する場合には次のように書くことができます。&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sorted = [array sortedArrayUsingComparator:makeCompByDir(makeCompByKind(compByName))];&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;まとめ&lt;/h4&gt;&lt;p&gt;Objective-Cにおいて、ブロックオブジェクトで高階関数を用いてオブジェクトのソートを行う方法を紹介しました。&lt;/p&gt;&lt;h4&gt;関連項目&lt;/h4&gt;&lt;li&gt;&lt;br /&gt;
&lt;li&gt;&lt;a href="http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/Blocks/Articles/00_Introduction.html"&gt;Blocks Programming Topics&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;&lt;a href="http://developer.apple.com/library/mac/#documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html"&gt;Grand Central Dispatch (GCD) Reference&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;
&lt;/li&gt;&lt;br /&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5191809332257264217-8996313170141753005?l=safx-dev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/D6-VFY6GuW6RWRb9fsjqKfIi4UY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/D6-VFY6GuW6RWRb9fsjqKfIi4UY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/D6-VFY6GuW6RWRb9fsjqKfIi4UY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/D6-VFY6GuW6RWRb9fsjqKfIi4UY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/TFCRl/~4/y_fsXJq9--M" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://safx-dev.blogspot.com/feeds/8996313170141753005/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://safx-dev.blogspot.com/2010/11/objective-c.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/8996313170141753005?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/8996313170141753005?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/TFCRl/~3/y_fsXJq9--M/objective-c.html" title="Objective-C上でブロックオブジェクトによる高階関数を用いてソートする方法について" /><author><name>safx developer</name><uri>http://www.blogger.com/profile/13931453776402259724</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/-xmu-GKy-rZo/TY10GvG4LYI/AAAAAAAAAgo/2rul0qNef4Q/s220/%255Bsafx%255D%2B-%2B%25E3%2581%2595%25E3%2581%25B5%25E9%2596%258B%25E7%2599%25BA%25E8%2580%2585.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/_XbtP-rrPvTg/TPON_uks0ZI/AAAAAAAAAS0/SY9W84Zdp9I/s72-c/P5104022.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://safx-dev.blogspot.com/2010/11/objective-c.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CE8HSXo8fyp7ImA9WhdWEEg.&quot;"><id>tag:blogger.com,1999:blog-5191809332257264217.post-7836808815283527747</id><published>2010-11-26T22:33:00.005+09:00</published><updated>2011-09-03T21:27:18.477+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-03T21:27:18.477+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="iPhone" /><category scheme="http://www.blogger.com/atom/ns#" term="AudioQueue" /><category scheme="http://www.blogger.com/atom/ns#" term="CFNetwork" /><title>Audio Queue Serviceを用いたネットワークストリーミングによるオーディオ再生</title><content type="html">&lt;p&gt;以前の記事「&lt;a href="http://safx-dev.blogspot.com/2010/11/cfnetworkhttp.html?utm_source=BP_recent"&gt;CFNetworkフレームワークを用いた入力HTTPストリームの作成&lt;/a&gt;」でネットワークからデータを取得する方法について述べました。今回はここから、Audio File Stream ServicesとAudio Queue Servicesを用いてオーディオ再生を行う方法について説明します。なお、詳細はAppleのドキュメント「&lt;a href="http://developer.apple.com/library/mac/#documentation/MusicAudio/Conceptual/AudioQueueProgrammingGuide/Introduction/Introduction.html"&gt;Audio Queue Services Programming Guide&lt;/a&gt;」を参照してください。&lt;/p&gt;&lt;a href="http://picasaweb.google.com/lh/photo/FoaHx-GBurwmDPn9LLblPQ?feat=embedwebsite"&gt;&lt;img src="http://lh3.ggpht.com/_XbtP-rrPvTg/TO-2JTfCQYI/AAAAAAAAASs/Bm5OMn5OXvo/s400/PB269277.jpg" height="300" width="400" /&gt;&lt;/a&gt; &lt;a name='more'&gt;&lt;/a&gt; &lt;h4&gt;概要&lt;/h4&gt;&lt;p&gt;ストリーミングオーディオを再生するには次の手順を踏みます。&lt;/p&gt;&lt;ol&gt;&lt;li&gt;CFNetworkを用いてストリームデータを取得&lt;/li&gt;
&lt;li&gt;Audio File Stream Servicesを用いてネットワークパケットを解析&lt;/li&gt;
&lt;li&gt;Audio Queue Servicesを用いてそのオーディオを再生&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;この流れを次に示します。矩形はオブジェクト、丸四角はコールバックを示し、実線はオブジェクトなどの生成、破線はオーディオデータの流れを示しています。そして、破線上の赤い文字は発生条件、黒い文字は呼び出し関数を示しています。&lt;/p&gt;&lt;a href="http://picasaweb.google.com/lh/photo/z3wJJHXqUC9KqmUcoOF2-w?feat=embedwebsite"&gt;&lt;img src="http://lh6.ggpht.com/_XbtP-rrPvTg/TO-2JPUefBI/AAAAAAAAASk/J-ZvtviPuLE/s640/streamingaudio.png" height="591" width="640" /&gt;&lt;/a&gt;  &lt;h4&gt;1. CFReadSream (CFNetwork)&lt;/h4&gt;&lt;p&gt;CFNetworkのCFReadSreamを用いてネットワーク越しにデータを取得します。基本的な部分は以前の記事「&lt;a href="http://safx-dev.blogspot.com/2010/11/cfnetworkhttp.html?utm_source=BP_recent"&gt;CFNetworkフレームワークを用いた入力HTTPストリームの作成&lt;/a&gt;」と同様なので、ここでは詳細は述べません。&lt;/p&gt;&lt;p&gt;データを取得したときにイベントkCFStreamEventHasBytesAvailableが発生で、AudioFileStreamParseBytesによってAudioFileStreamにデータを渡すようにします。具体的には次のように書きます。&lt;/p&gt;&lt;pre class="brush:cpp"&gt;switch(event) {
    case kCFStreamEventHasBytesAvailable: {
        UInt8 buf[4096];
        CFIndex bytesRead = CFReadStreamRead(stream, buf, sizeof(buf));
        AudioFileStreamParseBytes(globalAudioFileStream, bytesRead, buf, 0);
    } break;
&lt;/pre&gt;&lt;h4&gt;2. Audio File Stream Services&lt;/h4&gt;&lt;p&gt;ネットワークから得られたデータはオーディオパケット単位で得られるわけではない上、オーディオパケット以外のデータとしてプロパティが混じっています。次の図はこれを概念化したものです。&lt;/p&gt;&lt;a href="http://picasaweb.google.com/lh/photo/Zsi3g06zCQTnc_168231Vg?feat=embedwebsite"&gt;&lt;img src="http://lh4.ggpht.com/_XbtP-rrPvTg/TO-2JLmIssI/AAAAAAAAASo/0Dvfq0JNmkA/s640/streampackets.png" height="282" width="640" /&gt;&lt;/a&gt;  &lt;p&gt;オーディオデータは(上図の状態0)のようにオーディオパケット(青)とプロパティ(紫)が混じっています。さらに、ネットワークから得られるデータ場合はオーディオパケットなどの境界で適切に分割されていません(上図の状態1)。そのため、Audio File Stream Servicesによってオーディオデータをパケット単位で取得することと、ストリーム中のプロパティを取得することを行います(上図の状態2)。&lt;/p&gt;&lt;p&gt;Audio File Stream Servicesで行うべき処理について次に示します。&lt;/p&gt;&lt;ol&gt;&lt;li&gt;関数AudioFileStreamOpenによって新規オーディオストリーム解析器を作成&lt;br /&gt;
オーディオデータとメタデータ (プロパティ) のためにコールバック関数AudioFileStream&lt;em&gt;PacketsProcとAudioFileStream&lt;/em&gt;PropertyListenerProcを渡す。&lt;/li&gt;
&lt;li&gt;先ほどのCFReadSreamからストリームデータを取得&lt;br /&gt;
実際には可能な限りギャップなしでデータを解析器に継続的に渡すようにする必要があります。&lt;/li&gt;
&lt;li&gt;ストリームの解析が終了時に関数AudioFileStreamCloseを呼び出して、解析器のクローズとデアロケートを行う&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;また、2つのコールバックでは次のような処理を行います。&lt;/p&gt;&lt;ul&gt;&lt;li&gt;プロパティコールバック&lt;br /&gt;
プロパティ値を取得することができます (関数AudioFileStreamGetPropertyInfoとAudioFileStreamGetPropertyを呼ぶ)   今回は再生可能な状態になった時点でAudio Queueを作成します。&lt;/li&gt;
&lt;li&gt;オーディオデータコールバック&lt;br /&gt;
データの再生、ファイルへの保存といった処理を行うとよいです。&lt;br /&gt;
今回はバッファを作成して、それをオーディオキューに追加します。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;次の2つのコード片はこれらコールバックの重要な部分だけの抜き出したものです。&lt;/p&gt;&lt;pre class="brush:cpp"&gt;// myAudioFileStream_PropertyListenerProc
switch(inPropertyID){
    case kAudioFileStreamProperty_ReadyToProducePackets: {
        AudioStreamBasicDescription asbd;
        UInt32 size = sizeof(asbd);
        AudioFileStreamGetProperty(inAudioFileStream, kAudioFileStreamProperty_DataFormat,
                     &amp;amp;size, (void*) &amp;amp;asbd);
        AudioQueueNewOutput(&amp;amp;asbd, &amp;amp;myAudioQueueOutputCallback,
                     NULL, CFRunLoopGetCurrent(), 
                     kCFRunLoopCommonModes, 0,
                     &amp;amp;globalAudioQueue);
        AudioQueueSetParameter(globalAudioQueue, kAudioQueueParam_Volume, 1.0);
        AudioQueueStart(globalAudioQueue, NULL);
        break;


// myAudioFileStream_PacketsProc
AudioQueueBufferRef aqbuf;
OSStatus err = AudioQueueAllocateBufferWithPacketDescriptions(globalAudioQueue, inNumberBytes,
                                                              inNumberPackets, &amp;amp;aqbuf);
memcpy(aqbuf-&amp;gt;mAudioData, inInputData, inNumberBytes);
aqbuf-&amp;gt;mAudioDataByteSize = inNumberBytes;    
AudioQueueEnqueueBuffer(globalAudioQueue, aqbuf, inNumberPackets, inPacketDescriptions);&lt;/pre&gt;&lt;h4&gt;3. Audio Queue Services&lt;/h4&gt;&lt;p&gt;通常、オーディオキューコールバック関数ではバッファを再利用するようなコードを書きますが、今回の例では作成したバッファを削除しています。&lt;/p&gt;&lt;pre&gt;&lt;code&gt;AudioQueueFreeBuffer(inAQ, inBuffer);&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;まとめ&lt;/h4&gt;&lt;p&gt;Audio FileStream ServicesとAudio Queue Servicesを用いてオーディオ再生を行う方法について説明しました。なお、この例ではコードを簡潔にするためにオーディオバッファを毎回作成、破棄を行っていますが、実際にはメモリ効率のため使い回す必要があります。&lt;/p&gt;&lt;h4&gt;関連項目&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://safx-dev.blogspot.com/2010/11/cfnetworkhttp.html?utm_source=BP_recent"&gt;さふ開発日記: CFNetworkフレームワークを用いた入力HTTPストリームの作成&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://developer.apple.com/library/mac/#documentation/MusicAudio/Conceptual/AudioQueueProgrammingGuide/Introduction/Introduction.html"&gt;Audio Queue Services Programming Guide: Introduction&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5191809332257264217-7836808815283527747?l=safx-dev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/72HX99n3f_CU2Ao3jiULMFkEA_I/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/72HX99n3f_CU2Ao3jiULMFkEA_I/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/72HX99n3f_CU2Ao3jiULMFkEA_I/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/72HX99n3f_CU2Ao3jiULMFkEA_I/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/TFCRl/~4/v4wqd28asT0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://safx-dev.blogspot.com/feeds/7836808815283527747/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://safx-dev.blogspot.com/2010/11/audio-queue-service.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/7836808815283527747?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/7836808815283527747?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/TFCRl/~3/v4wqd28asT0/audio-queue-service.html" title="Audio Queue Serviceを用いたネットワークストリーミングによるオーディオ再生" /><author><name>safx developer</name><uri>http://www.blogger.com/profile/13931453776402259724</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/-xmu-GKy-rZo/TY10GvG4LYI/AAAAAAAAAgo/2rul0qNef4Q/s220/%255Bsafx%255D%2B-%2B%25E3%2581%2595%25E3%2581%25B5%25E9%2596%258B%25E7%2599%25BA%25E8%2580%2585.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/_XbtP-rrPvTg/TO-2JTfCQYI/AAAAAAAAASs/Bm5OMn5OXvo/s72-c/PB269277.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://safx-dev.blogspot.com/2010/11/audio-queue-service.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CE8CR3Y6fyp7ImA9WhdWEEg.&quot;"><id>tag:blogger.com,1999:blog-5191809332257264217.post-4172298926438849626</id><published>2010-11-21T00:47:00.011+09:00</published><updated>2011-09-03T21:27:46.817+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-03T21:27:46.817+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="統一型識別子" /><category scheme="http://www.blogger.com/atom/ns#" term="UTI" /><category scheme="http://www.blogger.com/atom/ns#" term="iPhone" /><category scheme="http://www.blogger.com/atom/ns#" term="カスタムURLスキーム" /><category scheme="http://www.blogger.com/atom/ns#" term="plist" /><category scheme="http://www.blogger.com/atom/ns#" term="クイックルック" /><title>iOSアプリケーションを特定のファイル形式に対応させる方法について</title><content type="html">&lt;a href="http://picasaweb.google.com/lh/photo/zNRxmcf98ArYyVecCYy8KQ?feat=embedwebsite"&gt;&lt;img src="http://lh6.ggpht.com/_XbtP-rrPvTg/TOfrvv9IdsI/AAAAAAAAASY/3GquGg_Kd5A/s400/Screen%20shot%202010-11-20%20at%2022.04.13.png" height="209" width="400" /&gt;&lt;/a&gt; &lt;p&gt;前回の記事「&lt;a href="http://safx-dev.blogspot.com/2010/11/uidocumentinteractioncontroller.html"&gt;UIDocumentInteractionControllerを用いて別アプリケーションを開くメニューを表示する方法について&lt;/a&gt;」では選択したファイルからクイックビューや対応可能なアプリケーションを呼び出す方法について説明しました。今回は、アプリケーションを特定のファイル形式に対応させ、前回の記事で用いたUIDocumentInteractionControllerから利用可能にさせる方法を説明し、ここで利用する統一型識別子 (UTI) についても簡単に説明します。&lt;/p&gt;&lt;p&gt;詳細はAppleの公式ドキュメント「iOS Application Programming Guide」の「&lt;a href="https://developer.apple.com/library/ios/#documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/StandardBehaviors/StandardBehaviors.html#//apple_ref/doc/uid/TP40007072-CH4-SW11"&gt;Implementing Standard Application Behaviors&lt;/a&gt;」を参照してください。なお、この文書はiOSの場合について言及しており、Mac OS Xの場合とは詳細が異なります。&lt;/p&gt;&lt;a name='more'&gt;&lt;/a&gt; &lt;h4&gt;Info.plist&lt;/h4&gt;&lt;p&gt;アプリケーションが特定のドキュメントタイプ (ファイル形式) に対応するには、Info.plistでキーCFBundleDocumentTypesを設定する必要があります。CFBundleDocumentTypesはディクショナリ型の配列で、各ディクショナリがひとつのドキュメントタイプについて指定しています。&lt;/p&gt;&lt;p&gt;iOSにおけるCFBundleDocumentTypes内の各ディクショナリは次のキーを含んでいます。&lt;/p&gt;&lt;ul&gt;&lt;li&gt;CFBundleTypeName&lt;br /&gt;
(文字列) ドキュメントタイプの名前 (必須)&lt;/li&gt;
&lt;li&gt;CFBundleTypeIconFiles&lt;br /&gt;
(配列) このドキュメントタイプに対応するアイコン画像リソースを示すファイル名の配列。22×29ピクセル (iPad用は64×64) のアイコンを用意する、らしいのですがどこで使用されているのかいまいちよくわかっていません。なければアプリケーションアイコンから生成されるようです&lt;/li&gt;
&lt;li&gt;LSItemContentTypes&lt;br /&gt;
(配列) このドキュメントタイプがサポートする統一型識別子 (UTI; Uniform Type Identifier) 形式の文字列の配列&lt;/li&gt;
&lt;li&gt;LSHandlerRank&lt;br /&gt;
(文字列) アプリケーションがこのドキュメントタイプをどの程度サポートしているかを示すランク。優先度が高いほうから順番に、 Owner (このタイプの作成可能) &gt; Alternate (このタイプの閲覧可能) &gt; None (扱えないがドロップは可能) &gt; Default (ドロップの不可)&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;例えば、アプリケーションをHTMLを含むテキストファイル全般に対応させたい場合には、Info.plistで次のように指定します。テキストファイル全般に対応したUTI形式は「public.text」ですので、LSItemContentTypesではそれを指定しています。&lt;/p&gt;&lt;img src="http://lh3.ggpht.com/_XbtP-rrPvTg/TOfrvkCBKBI/AAAAAAAAASU/Qu7N1EmY2Lc/s800/Screen%20shot%202010-11-20%20at%2022.14.38.png" /&gt;  &lt;h4&gt;URLリクエストの受け入れ&lt;/h4&gt;&lt;p&gt;Info.plistを設定後、別のアプリケーションから与えられるファイルを扱えるようにします。これには「&lt;a href="http://safx-dev.blogspot.com/2010/10/iosurl.html"&gt;独自カスタムURLスキームを設定する方法&lt;/a&gt;」と同様に、&lt;code&gt;application:handleOpenURL:&lt;/code&gt;もしくは&lt;code&gt;application:didFinishLaunchingWithOptions:&lt;/code&gt;を利用します。コード例を次に示します。&lt;/p&gt;&lt;pre class="brush:cpp"&gt;- (BOOL)application:(UIApplication*)application handleOpenURL:(NSURL*)url {
    if ([url.scheme isEqualToString:@"file"]) {
        NSString* str = [NSString stringWithContentsOfURL:url
                           encoding:NSUTF8StringEncoding error:nil];
        viewController.textView.text = str;
        return YES;        
    } else if ([url.scheme isEqualToString:@"mySampleApp"]) {
        // カスタムURLスキームの処理 (省略)
    }
}&lt;/pre&gt;&lt;h4&gt;統一型識別子 (UTI) について&lt;/h4&gt;&lt;p&gt;キーLSItemContentTypesで用いるUTI形式は同じファイル形式を意味する拡張子、OSType、MIMEタイプをまとめて扱えるようにするものです。例えば、OSTypeのJPEG、拡張子の.jpg、拡張子の.jpeg、MIMEタイプのimage/jpegなどはUTI形式では「public.jpeg」と表現できます。&lt;/p&gt;&lt;ul&gt;&lt;li&gt;UTIは階層構成で、ファイルについてはpublic.dataがルート&lt;/li&gt;
&lt;li&gt;UTIの表記はDNS表記と似た形式で、英数字とドット(.)とハイフン(-)のみ使用可能&lt;/li&gt;
&lt;li&gt;ドメインpublicは予約ドメイン&lt;/li&gt;
&lt;li&gt;多重継承も可能&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;なお、画像やテキストなどの一般的な形式は既に定義されており、「&lt;a href="http://developer.apple.com/library/mac/#documentation/Miscellaneous/Reference/UTIRef/Articles/System-DeclaredUniformTypeIdentifiers.html#//apple_ref/doc/uid/TP40009259-SW1"&gt;System-Declared Uniform Type Identifiers&lt;/a&gt;」の表1にあるシステム定義のUTIをグラフ化したものは次のようになります。これはシステム定義済みのもの全てを示しておらず、WindowsビットマップやAdobe Reader形式などは別の表で示されているので、このグラフには存在しません。&lt;/p&gt;&lt;a href="http://picasaweb.google.com/lh/photo/zNRxmcf98ArYyVecCYy8KQ?feat=embedwebsite"&gt;&lt;img src="http://lh6.ggpht.com/_XbtP-rrPvTg/TOfrvDNCwtI/AAAAAAAAASQ/K4C2QkRDS4o/s800/uti2.png" height="588" width="800" /&gt;&lt;/a&gt;  &lt;p&gt;&lt;a href="https://docs.google.com/leaf?id=0B5b2b-C9jyfjMzJkZjg4ZjgtOTJkOS00NTU0LTk2OTgtYzFjNjg5Y2FmMzI4&amp;hl=en"&gt;上記画像のSVGファイル&lt;/a&gt; (最近のブラウザなら、リンク先の「Open」で表示することができます)&lt;/p&gt;&lt;h4&gt;まとめ&lt;/h4&gt;&lt;p&gt;アプリケーションを特定のファイル形式に対応させる方法と統一型識別子 (UTI) について説明しました。&lt;/p&gt;&lt;h4&gt;関連項目&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://safx-dev.blogspot.com/2010/11/uidocumentinteractioncontroller.html"&gt;さふ開発日記: UIDocumentInteractionControllerを用いて別アプリケーションを開くメニューを表示する方法について&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://safx-dev.blogspot.com/2010/10/iosurl.html"&gt;さふ開発日記: iOSで独自カスタムURLスキームを設定する方法について&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.apple.com/library/ios/#documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/StandardBehaviors/StandardBehaviors.html#//apple_ref/doc/uid/TP40007072-CH4-SW11"&gt;iOS Application Programming Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://developer.apple.com/library/ios/#documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/TP40009249-SW1"&gt;Information Property List Key Reference&lt;/a&gt; Info.plistで用いるキーについての解説&lt;/li&gt;
&lt;li&gt;&lt;a href="http://developer.apple.com/library/mac/#documentation/FileManagement/Conceptual/understanding_utis/understand_utis_intro/understand_utis_intro.html"&gt;Uniform Type Identifiers Overview&lt;/a&gt; 統一型識別子 (UTI) について&lt;/li&gt;
&lt;li&gt;&lt;a href="http://developer.apple.com/library/mac/#documentation/Miscellaneous/Reference/UTIRef/Articles/System-DeclaredUniformTypeIdentifiers.html#//apple_ref/doc/uid/TP40009259-SW1"&gt;Uniform Type Identifiers Reference&lt;/a&gt; システム定義済みのUTI&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5191809332257264217-4172298926438849626?l=safx-dev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/UZE9c-SOmTquzwIHlvfOopmKc58/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/UZE9c-SOmTquzwIHlvfOopmKc58/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/UZE9c-SOmTquzwIHlvfOopmKc58/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/UZE9c-SOmTquzwIHlvfOopmKc58/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/TFCRl/~4/qPCPRDHhYFs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://safx-dev.blogspot.com/feeds/4172298926438849626/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://safx-dev.blogspot.com/2010/11/ios_21.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/4172298926438849626?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/4172298926438849626?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/TFCRl/~3/qPCPRDHhYFs/ios_21.html" title="iOSアプリケーションを特定のファイル形式に対応させる方法について" /><author><name>safx developer</name><uri>http://www.blogger.com/profile/13931453776402259724</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/-xmu-GKy-rZo/TY10GvG4LYI/AAAAAAAAAgo/2rul0qNef4Q/s220/%255Bsafx%255D%2B-%2B%25E3%2581%2595%25E3%2581%25B5%25E9%2596%258B%25E7%2599%25BA%25E8%2580%2585.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/_XbtP-rrPvTg/TOfrvv9IdsI/AAAAAAAAASY/3GquGg_Kd5A/s72-c/Screen%20shot%202010-11-20%20at%2022.04.13.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://safx-dev.blogspot.com/2010/11/ios_21.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CE8MRXo-cCp7ImA9WhdWEEg.&quot;"><id>tag:blogger.com,1999:blog-5191809332257264217.post-5744188790920984334</id><published>2010-11-18T20:37:00.011+09:00</published><updated>2011-09-03T21:28:04.458+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-03T21:28:04.458+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="UIDocumentInteractionController" /><category scheme="http://www.blogger.com/atom/ns#" term="ライブラリ" /><category scheme="http://www.blogger.com/atom/ns#" term="iPhone" /><category scheme="http://www.blogger.com/atom/ns#" term="クイックルック" /><title>UIDocumentInteractionControllerを用いて別アプリケーションを開くメニューを表示する方法について</title><content type="html">&lt;img src="http://lh6.ggpht.com/_XbtP-rrPvTg/TOUO0P38ovI/AAAAAAAAASA/RhyOnZFNhf4/s800/q1a.png" /&gt; &lt;p&gt;メール (Mail.app) などで添付ファイルを長押し (タップアンドホールド) すると、「クイックルック (Quick Look)」を含めた対応可能なアプリケーションを選択させるためのアクションシートが表示されます。今回はこのアクションシートの表示の方法を説明します。&lt;/p&gt;&lt;a name='more'&gt;&lt;/a&gt; &lt;p&gt;このアクションシートの表示にはクラス&lt;code&gt;&lt;a href="http://developer.apple.com/library/ios/#documentation/uikit/reference/UIDocumentInteractionController_class/Reference/Reference.html"&gt;UIDocumentInteractionController&lt;/a&gt;&lt;/code&gt;を利用します。その使用例を次に示します。このコントローラは命名規則からわかるように自動解放されるため、retainしておく必要があります。&lt;/p&gt;&lt;pre class="brush:cpp"&gt;&amp;nbsp; - (void)openMenuButtonClicked:(id)sender {
      UIDocumentInteractionController* diController = [UIDocumentInteractionController interactionControllerWithURL:url];
      diController.delegate = self;
  
      if ([diController presentOptionsMenuFromRect:self.view.frame inView:self.view animated:YES])
          [diController retain];
  }
  - (UIViewController*)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController*)controller {
      return self; // プレビュー用に用いるビューコントローラ
  }
? - (void)documentInteractionControllerDidEndPreview:(UIDocumentInteractionController *)controller {
?     [controller autorelease];
? }&lt;/pre&gt;&lt;blockquote&gt;2010.12.21追記: コントローラの解放周りのコードが間違っており、正しく解放されない場合があります。詳細は次の記事を参照してください。&lt;ul&gt;&lt;li&gt;&lt;a href="http://safx-dev.blogspot.com/2010/12/uidocumentinteractioncontrollerdelegate.html"&gt;さふ開発日記: UIDocumentInteractionControllerDelegateの処理の流れについて&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/blockquote&gt;&lt;p&gt;また、メールでのタップのようにいきなり対象ファイルをプレビュー表示させたいときは&lt;code&gt;presentPreviewAnimated:&lt;/code&gt;を用います。&lt;/p&gt;&lt;a href="http://picasaweb.google.com/lh/photo/q6E2DpP7xpU-HHh31YzBEw?feat=embedwebsite"&gt;&lt;img src="http://lh6.ggpht.com/_XbtP-rrPvTg/TOUO0WT7ocI/AAAAAAAAASE/JTcFpXH_krY/s288/q2.png" height="288" width="192" /&gt;&lt;/a&gt;  &lt;p&gt;ちなみに対応アプリケーションが増えると次のようになります。&lt;/p&gt;&lt;a href="http://picasaweb.google.com/lh/photo/nrBdw9C-ndJQNh83-B0PPg?feat=embedwebsite"&gt;&lt;img src="http://lh5.ggpht.com/_XbtP-rrPvTg/TOUO0ikxb1I/AAAAAAAAASI/y0Y5l1Erba8/s288/q3.png" height="288" width="192" /&gt;&lt;/a&gt;  &lt;h4&gt;関連項目&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://safx-dev.blogspot.com/2010/12/uidocumentinteractioncontrollerdelegate.html"&gt;さふ開発日記: UIDocumentInteractionControllerDelegateの処理の流れについて&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://safx-dev.blogspot.com/2010/12/quick-look-framework%E3%82%92%E7%94%A8%E3%81%84%E3%81%9F%E3%83%97%E3%83%AC%E3%83%93%E3%83%A5%E3%83%BC%E8%A1%A8%E7%A4%BA%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6.html?utm_source=BP_recent"&gt;さふ開発日記: Quick Look Frameworkを用いたプレビュー表示について&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://developer.apple.com/library/ios/#documentation/FileManagement/Conceptual/DocumentInteraction_TopicsForIOS/Introduction/Introduction.html#//apple_ref/doc/uid/TP40010409-SW1"&gt;Document Interaction Programming Topics for iOS: About Document Interaction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://developer.apple.com/library/ios/#documentation/uikit/reference/UIDocumentInteractionController_class/Reference/Reference.html"&gt;クラスリファレンスUIDocumentInteractionController&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://developer.apple.com/library/ios/#documentation/FileManagement/Conceptual/understanding_utis/understand_utis_intro/understand_utis_intro.html"&gt;Uniform Type Identifiers Overview&lt;/a&gt; 統一型識別子 (UTI; Uniform Type Identifier) についての解説&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5191809332257264217-5744188790920984334?l=safx-dev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/OLtQXZSzBfwPAmMSrmhBU0H0ceQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/OLtQXZSzBfwPAmMSrmhBU0H0ceQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/OLtQXZSzBfwPAmMSrmhBU0H0ceQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/OLtQXZSzBfwPAmMSrmhBU0H0ceQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/TFCRl/~4/ebAKApti7LQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://safx-dev.blogspot.com/feeds/5744188790920984334/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://safx-dev.blogspot.com/2010/11/uidocumentinteractioncontroller.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/5744188790920984334?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5191809332257264217/posts/default/5744188790920984334?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/TFCRl/~3/ebAKApti7LQ/uidocumentinteractioncontroller.html" title="UIDocumentInteractionControllerを用いて別アプリケーションを開くメニューを表示する方法について" /><author><name>safx developer</name><uri>http://www.blogger.com/profile/13931453776402259724</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/-xmu-GKy-rZo/TY10GvG4LYI/AAAAAAAAAgo/2rul0qNef4Q/s220/%255Bsafx%255D%2B-%2B%25E3%2581%2595%25E3%2581%25B5%25E9%2596%258B%25E7%2599%25BA%25E8%2580%2585.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/_XbtP-rrPvTg/TOUO0P38ovI/AAAAAAAAASA/RhyOnZFNhf4/s72-c/q1a.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://safx-dev.blogspot.com/2010/11/uidocumentinteractioncontroller.html</feedburner:origLink></entry></feed>

