<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-42067579805640535</id><updated>2012-01-29T02:19:47.824+09:00</updated><category term='Windows XP'/><category term='GAEO 0.21'/><category term='Hack'/><category term='文法'/><category term='libHaru'/><category term='動画'/><category term='名刺'/><category term='UI'/><category term='Windows'/><category term='ビルド'/><category term='翻訳'/><category term='iPhone OS 3.0'/><category term='iPhone OS 3.1.2'/><category term='Apple'/><category term='Xcode 3.1.3'/><category term='iOS 4.1'/><category term='ログ'/><category term='本'/><category term='開発'/><category term='Django 1.1'/><category term='git'/><category term='Python 2.5.2'/><category term='Google App Engine 1.3.0'/><category term='コミュニティ'/><category term='Mac OS X'/><category term='App Store'/><category term='非同期処理'/><category term='Flex'/><category term='アプリケーション'/><category term='Processing 1.0.9'/><category term='App Engine Patch'/><category term='Flash CS4'/><category term='PDF'/><category term='デザインパターン'/><category term='Tips'/><category term='Boot Camp'/><category term='Unicode'/><category term='テンプレート'/><category term='Firefox'/><category term='iPhone'/><category term='GAEO'/><category term='地図'/><category term='Django'/><category term='Python 2.5.4'/><category term='iPhone OS 3.1.3'/><category term='.NET'/><category term='Pipe'/><category term='Python'/><category term='PIL'/><category term='doxygen'/><category term='Xcode'/><category term='ecto'/><category term='Google App Engine 1.2.7'/><category term='github'/><category term='Core Data'/><category term='Xcode 3.2.6'/><category term='clang'/><category term='Scala'/><category term='Xcode 4.0'/><category term='plugin'/><category term='公衆無線LAN'/><category term='Core Animation'/><category term='Processing'/><category term='C言語'/><category term='Android SDK 1.0'/><category term='SSL'/><category term='canvas'/><category term='勉強会'/><category term='Flex SDK 3'/><category term='iPhone OS 4.0.2'/><category term='cocos2d'/><category term='セキュリティ'/><category term='無線LAN'/><category term='Sphinx'/><category term='IE6'/><category term='gdb'/><category term='Remember the Milk'/><category term='バグ'/><category term='BlueTooth'/><category term='ssh'/><category term='ATOK'/><category term='Google'/><category term='英語'/><category term='GTD'/><category term='Xcode 4.2'/><category term='Ruby'/><category term='生産性'/><category term='iOS 4.2.1'/><category term='Linux'/><category term='Cocoa'/><category term='OmniFocus'/><category term='コマンドライン'/><category term='国際化'/><category term='設計'/><category term='勉強'/><category term='Xcode 3.2.5'/><category term='仕事術'/><category term='ドキュメント'/><category term='お知らせ'/><category term='Byline'/><category term='iPhone OS 2.2'/><category term='iOS 4.3.5'/><category term='懇親会'/><category term='cocos2d 0.8'/><category term='ゲーム'/><category term='ActionScript 3'/><category term='Python 2.6.1'/><category term='iMovie'/><category term='Mercurial'/><category term='HTTP'/><category term='デバッグ'/><category term='ライブラリ'/><category term='Flash'/><category term='RSS'/><category term='Mac OS X 10.5'/><category term='Private API'/><category term='パフォーマンス'/><category term='Mercurial 1.4.3'/><category term='Xcode 3.2.2'/><category term='Python 2.6.2'/><category term='vim'/><category term='cron'/><category term='iMac'/><category term='ライフハック'/><category term='SoftBank'/><category term='IE7'/><category term='Mac OS X 10.6'/><category term='jQuery'/><category term='インストール'/><category term='デザイン'/><category term='エラー'/><category term='Firefox 3.0.8'/><category term='URL'/><category term='Xcode 4.0.2'/><category term='Blogger'/><category term='ImageIO'/><category term='設定'/><category term='テスト'/><category term='jWeeklyForecast'/><category term='iPhone OS 2.1'/><category term='HTML'/><category term='Core Location'/><category term='JavaScript'/><category term='Android SDK 2.2'/><category term='Xcode 4.0.1'/><category term='Core Graphics'/><category term='User-Agent'/><category term='Redmine'/><category term='Petrus Blogger'/><category term='Twitter'/><category term='iOS 5.0.1'/><category term='Webサービス'/><category term='チュートリアル'/><category term='iPhone 3GS'/><category term='YourTurn'/><category term='iOS 4.3.2'/><category term='Keychain'/><category term='iOS 3.1.3'/><category term='環境変数'/><category term='ThinkingRock'/><category term='Objective-C'/><category term='旅行'/><category term='iOS 4.3.1'/><category term='iOS 4.0'/><category term='認証'/><category term='Android'/><category term='基礎'/><category term='Yahoo'/><category term='スタイラス'/><category term='iOS 3.2'/><category term='Firefox 3.5b4'/><category term='Evernote'/><category term='レビュー'/><category term='Maven 2'/><category term='Xcode 3.1.1'/><category term='iOS 4.3.3'/><category term='Cookie'/><category term='iPhone OS 3.2'/><category term='Sphinx 0.6.4'/><category term='ショートカットキー'/><category term='ニコニコ動画'/><category term='Python 2.5.1'/><category term='Java'/><category term='API'/><category term='Google App Engine'/><category term='Three20'/><category term='C#'/><category term='Xcode 3.1.2'/><category term='Jenkins'/><category term='cocos2d 0.8rc'/><category term='Google App Engine 1.2.0'/><category term='IE'/><category term='ソースコード'/><category term='iPad'/><category term='マウス'/><category term='画像'/><title type='text'>A-Liaison BLOG</title><subtitle type='html'>使えそうな情報は何でも共有しましょう。更新頻度＝月3～4回。</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://akisute.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://akisute.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default?start-index=101&amp;max-results=100'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>232</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-5041242169907030613</id><published>2012-01-29T02:19:00.003+09:00</published><updated>2012-01-29T02:19:47.871+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Cocoa'/><title type='text'>xxd を使って画像などのバイナリデータをソースコードに含める方法</title><content type='html'>iOS向けのライブラリやフレームワークを作成しているときに、どうしても画像などのバイナリデータをライブラリやフレームワークに含めたくなる時があります。たとえばUI系のフレームワークなどですね。このようなときに、たとえば静的ライブラリ（.aと.h）やフレームワーク（.framework）とセットで画像を一緒に同梱し、ユーザーのXcodeプロジェクトに一緒に含めてもらうという方法もあるのですが、この方法だと画像名がユーザーのプロジェクトに含まれている画像とかぶったりしてはいけませんし、管理が面倒になってしまいます。また、ライセンスがプロプライエタリなライブラリでは、画像などのリソースをあまり積極的にユーザーに公開したくないというニーズがあったりします。&lt;br /&gt;&lt;br /&gt;そこでxxdツールのご紹介です。&lt;a href="http://d.hatena.ne.jp/KishikawaKatsumi/"&gt;岸川先生&lt;/a&gt;に教えていただいたのですが、xxdというツールを使えばバイナリデータをC言語のヘッダファイルとして簡単に出力することができるらしいのです。これを使ってバイナリデータをライブラリ内部のソースコードの一部として配布してみましょう。&lt;br /&gt;&lt;br /&gt;xxdはvimに同梱されているので、最初からMac OS Xについてきます。使い方も非常に簡単です。&lt;pre&gt;xxd -i Sample.png&lt;/pre&gt;とすると、&lt;pre&gt;unsigned char Sample_png[] = {&lt;br /&gt;  0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,&lt;br /&gt;  0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x07, 0xfd, 0x00, 0x00, 0x04, 0x73,&lt;br /&gt;//中略&lt;br /&gt;unsigned int Sample_png_len = 589903;&lt;/pre&gt;このような感じでバイナリデータがC言語のヘッダファイルになって出力されます。あとはこれをNSDataにして、UIImageを生成することができます。NSDataを作る際には余計なデータコピーが発生しないdataWithBytesNoCopy:length:freeWhenDone:を使うことをお勧めします。&lt;pre class="prettyprint linenums"&gt;NSData *data_Sample_png = [NSData dataWithBytesNoCopy:Sample_png length:Sample_png_len freeWhenDone:NO];&lt;br /&gt;UIImage *image = [UIImage imageWithData:data_Sample_png];&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-5041242169907030613?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/5041242169907030613/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=5041242169907030613' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/5041242169907030613'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/5041242169907030613'/><link rel='alternate' type='text/html' href='http://akisute.com/2012/01/xxd.html' title='xxd を使って画像などのバイナリデータをソースコードに含める方法'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-4683887423781203880</id><published>2012-01-24T18:58:00.000+09:00</published><updated>2012-01-24T18:58:16.501+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Jenkins'/><category scheme='http://www.blogger.com/atom/ns#' term='ビルド'/><category scheme='http://www.blogger.com/atom/ns#' term='Xcode'/><category scheme='http://www.blogger.com/atom/ns#' term='Xcode 4.2'/><title type='text'>Jenkins を iOS アプリ開発に導入してみた (gcov編)</title><content type='html'>&lt;div class="separator" style="clear: both;"&gt;&lt;a href="http://3.bp.blogspot.com/-AHlViSUBNcY/Tx6AIAUiN-I/AAAAAAAACvE/c0XEIPKnfc0/s1600/%25E3%2582%25B9%25E3%2582%25AF%25E3%2583%25AA%25E3%2583%25BC%25E3%2583%25B3%25E3%2582%25B7%25E3%2583%25A7%25E3%2583%2583%25E3%2583%2588%2B2012-01-24%2B18.05.55.png" imageanchor="1" style=""&gt;&lt;img border="0" height="384" width="400" src="http://3.bp.blogspot.com/-AHlViSUBNcY/Tx6AIAUiN-I/AAAAAAAACvE/c0XEIPKnfc0/s400/%25E3%2582%25B9%25E3%2582%25AF%25E3%2583%25AA%25E3%2583%25BC%25E3%2583%25B3%25E3%2582%25B7%25E3%2583%25A7%25E3%2583%2583%25E3%2583%2588%2B2012-01-24%2B18.05.55.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;a href="http://akisute.com/2012/01/jenkins-ios-ghunit.html"&gt;前回&lt;/a&gt; はSenTestKitに続いてGHUnitを導入して、Jenkins上でGHUnitによるテストの自動実行を行いました。今回はさらにステップアップして、gcovを使用してコードカバレッジを取るようにしてみようかと思います。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■gcovを使ったコードカバレッジの取得&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;gcovとはgccに付属されているC言語用のカバレッジ測定ツールです。これを使うことで、C言語と、その拡張であるObjective-Cのコードカバレッジをバッチリ取得することができます。ということで早速プロジェクトに組み込んでみましょう。幸いにしてすでに先駆者の方がいらっしゃいました。&lt;br /&gt;&lt;a href="http://tech.naver.jp/blog/?p=706"&gt;http://tech.naver.jp/blog/?p=706&lt;/a&gt;&lt;br /&gt;基本的に上記に記載されている通りの手順で導入すれば簡単にgcovによるコードカバレッジの取得ができますが、実際にやってみたところ幾つか補足があるので追記します。&lt;br /&gt;&lt;br /&gt;先ほど紹介した記事では/Developer/usr/lib/libprofile_rt.dylibの追加と-lgcovの指定両方を行なっているのですが、私が試したところどちらか片方だけで成功するということがわかりました。具体的には以下のとおりになります。&lt;br /&gt;&lt;br /&gt;1. /Developer/usr/lib/libprofile_rt.dylibを使うパターン&lt;br /&gt;2. -lgcovを使うパターン&lt;br /&gt;&lt;br /&gt;それぞれ見ていきます。&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;1. /Developer/usr/lib/libprofile_rt.dylibを使うパターン&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;/Developer/usr/lib/libprofile_rt.dylibをプロジェクトに追加し、Other C Flagsの-fprofile-arcs -ftest-coverageを設定すればOKです。それ以外の手順は必要ありません。&lt;br /&gt;このパターンですとスムーズにgcovの結果を出力することができましたが、残念ながらこの方法はSimulator上でしか使用できません。というのも、/Developer/usr/lib/libprofile_rt.dylibがそもそもarmv6, armv7用のバイナリを含んでいないという問題があるのと、ライブラリ探索パス"/Developer"以下がDeviceビルド時に勝手にiphoneos.sdk以下の/Developerに置換されてしまうため、ビルド時にlibprofile_rt.dylibをリンカが発見できずエラーになる問題があるためです。基本的にSenTestingKitのようなSimulatorでしか実行しないビルドターゲットでやるのが良いと思われます。&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;2. -lgcovを使うパターン&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;参考: &lt;a href="http://stackoverflow.com/questions/5101014/code-coverage-not-showing-results-using-xcode-gcov/5140459#5140459"&gt;http://stackoverflow.com/questions/5101014/code-coverage-not-showing-results-using-xcode-gcov/5140459#5140459&lt;/a&gt;&lt;br /&gt;-lgcovをOther Linker Flagsに追加し、Generate Test Coverrage FilesとInstrument Program FlowにYESを指定すればOKです。それ以外の手順は必要ありません。&lt;br /&gt;このパターンですとlibgcovはarmv6, armv7でも動作するので実機でのカバレッジ取得ができるのですが、問題はそのままの設定でビルドして実行すると実行時にクラッシュします。これはlibgcovが実行時にカバレッジデータを書きだす際に、デフォルトの設定ではiOSのサンドボックスの外にアクセスしようとするため書き出しに失敗してしまうのが原因です。したがって上記参考URLに従ってGCOV_PREFIX環境変数を使いサンドボックス内部にカバレッジデータを書きだすように指定してやる必要があります。&lt;br /&gt;この方法は環境変数を実行時に設定する必要があって面倒なのと、カバレッジデータが書き出される箇所がJenkinsのビルドディレクトリの中ではなくiOSシミュレータまたは実機のサンドボックスの中になってしまうため、Jenkinsからカバレッジの取得を行うのが困難になってしまう問題があります。&lt;br /&gt;&lt;br /&gt;今回は1. のパターンを採用し、SenTestingKit上でSimulatorビルド時のカバレッジ取得だけを行うことにしました。GHUnitでも実機上での動作を諦めれば問題ないのですが・・・まだ課題が多い感じですね。&lt;br /&gt;&lt;br /&gt;ビルド設定ができたらビルドして、きちんとgcovコマンド経由でカバレッジが取得できていることを確認しましょう。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■gcovrを使ってCoberturaのXML形式に変換する&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;gcovのカバレッジデータの取得ができるようになったら、今度はJenkinsと連携させるために、gcovの出力をCoberturaというJava環境のカバレッジ計測ツールの出力するXML形式に変換する必要があります。これはJenkinsがgcovのカバレッジデータ出力の集計に対応していない為です。っていうかgcovの出力は単なるタブで区切られた文字列で人間以外にはとても優しくないので集計ができないのです。&lt;br /&gt;ここで、Python製のgcovrというツールをJenkinsサーバマシンに導入します。　gcovrをgcovの代わりに使うことで、CoberturaのXML形式で結果を出力できるようになるほか、カバレッジ計測対象となるファイルを簡単にフィルタリングできる（たとえばテストケースクラスのカバレッジなんか集計してもしょうがないので除外するなどできる）のが大きな魅力です。&lt;br /&gt;&lt;a href="http://wiki.hudson-ci.org/pages/viewpage.action?pageId=45482230"&gt;http://wiki.hudson-ci.org/pages/viewpage.action?pageId=45482230&lt;/a&gt;&lt;br /&gt;&lt;a href="https://software.sandia.gov/trac/fast/wiki/gcovr"&gt;https://software.sandia.gov/trac/fast/wiki/gcovr&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;インストールはMacマシンであれば非常に簡単で、以下のコマンドを打つだけです。&lt;pre&gt;sudo easy_install gcovr&lt;/pre&gt;インストールが完了したら、あとは&lt;pre&gt;gcovr --xml --output=cobertura-report.xml build/&lt;/pre&gt;とかやれば一発でbuildディレクトリ配下のすべてのカバレッジを計測結果を集計してXML形式で書きだしてくれます。&lt;br /&gt;ここでもし、テストケースのカバレッジは除外したいなどという要件がある場合は、&lt;pre&gt;gcovr --xml --exclude=".*/.*Test(s)?\.[(c)(cpp)(m)(mm)]" --output="cobertura-report.xml" build/&lt;/pre&gt;などとすればOKです。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■JenkinsのCoberturaプラグインを使って結果を集約する&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;CoberturaのXML形式で結果が取れるようになってしまえばあとは楽勝です。JenkinsにCoberturaプラグインをサクっとインストールして、&lt;br /&gt;&lt;a href="https://wiki.jenkins-ci.org/display/JENKINS/Cobertura+Plugin"&gt;https://wiki.jenkins-ci.org/display/JENKINS/Cobertura+Plugin&lt;/a&gt;&lt;br /&gt;あとは以下のようにJenkinsのジョブ設定を書いてしまうだけです。先述の通り、SenTestingKit上でSimulatorビルド時のカバレッジ取得だけを行いたいので、既存のSenTestingKit用単体テストジョブのXcodeビルドの後でgcovrを実行するシェルスクリプトを実行してやれば一発です。&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both;"&gt;&lt;a href="http://2.bp.blogspot.com/-4AfXsgxbtUw/Tx6AIaG44gI/AAAAAAAACvU/OWb8ubOVenM/s1600/%25E3%2582%25B9%25E3%2582%25AF%25E3%2583%25AA%25E3%2583%25BC%25E3%2583%25B3%25E3%2582%25B7%25E3%2583%25A7%25E3%2583%2583%25E3%2583%2588%2B2012-01-24%2B18.06.23.png" imageanchor="1" style=""&gt;&lt;img border="0" height="341" width="400" src="http://2.bp.blogspot.com/-4AfXsgxbtUw/Tx6AIaG44gI/AAAAAAAACvU/OWb8ubOVenM/s400/%25E3%2582%25B9%25E3%2582%25AF%25E3%2583%25AA%25E3%2583%25BC%25E3%2583%25B3%25E3%2582%25B7%25E3%2583%25A7%25E3%2583%2583%25E3%2583%2588%2B2012-01-24%2B18.06.23.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;カバレッジが取れるようになると断然見栄えがしますね。&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-4683887423781203880?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/4683887423781203880/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=4683887423781203880' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/4683887423781203880'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/4683887423781203880'/><link rel='alternate' type='text/html' href='http://akisute.com/2012/01/jenkins-ios-gcov.html' title='Jenkins を iOS アプリ開発に導入してみた (gcov編)'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-AHlViSUBNcY/Tx6AIAUiN-I/AAAAAAAACvE/c0XEIPKnfc0/s72-c/%25E3%2582%25B9%25E3%2582%25AF%25E3%2583%25AA%25E3%2583%25BC%25E3%2583%25B3%25E3%2582%25B7%25E3%2583%25A7%25E3%2583%2583%25E3%2583%2588%2B2012-01-24%2B18.05.55.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-8070796080926080037</id><published>2012-01-23T20:59:00.001+09:00</published><updated>2012-01-25T12:06:32.516+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Jenkins'/><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='Xcode'/><category scheme='http://www.blogger.com/atom/ns#' term='Xcode 4.2'/><title type='text'>Jenkins を iOS アプリ開発に導入してみた (GHUnit編)</title><content type='html'>&lt;div class="separator" style="clear: both;"&gt;&lt;a href="http://3.bp.blogspot.com/-oARnNMdBdBE/Tx1LI2oAekI/AAAAAAAACus/aqsLqVaSBKQ/s1600/%25E3%2582%25B9%25E3%2582%25AF%25E3%2583%25AA%25E3%2583%25BC%25E3%2583%25B3%25E3%2582%25B7%25E3%2583%25A7%25E3%2583%2583%25E3%2583%2588%2B2012-01-23%2B20.55.01.png" imageanchor="1" style=""&gt;&lt;img border="0" height="267" width="400" src="http://3.bp.blogspot.com/-oARnNMdBdBE/Tx1LI2oAekI/AAAAAAAACus/aqsLqVaSBKQ/s400/%25E3%2582%25B9%25E3%2582%25AF%25E3%2583%25AA%25E3%2583%25BC%25E3%2583%25B3%25E3%2582%25B7%25E3%2583%25A7%25E3%2583%2583%25E3%2583%2588%2B2012-01-23%2B20.55.01.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;a href="http://akisute.com/2012/01/jenkins-ios-sentestkit.html"&gt;前回&lt;/a&gt; はSenTestKitを用いてJenkins上で単体テストの自動実行を行いました。今回はGHUnitを使った単体テストの自動実行にチャレンジしてみたいと思います。またついでといっては何ですが、単体テスト時に必要になってくるモックを作成するためのライブラリOCMockも同時に導入してみようと思います。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■なぜGHUnitを使うのか&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;GHUnitを使うことで、SenTestingKitと比べて以下のようなメリットが得られます。&lt;ul&gt;&lt;li&gt;非同期処理のテストを行うための仕組みが用意されている（GHAsyncTestCase）これをSenTestingKitないし他のテスティングフレームワークでやろうとすると大変骨が折れます。&lt;/li&gt;&lt;li&gt;.app形式（要するに実際のiOSアプリケーション）でテストを実行するため、UIApplicationやUIWindowといったUIコンポーネントを使うクラスのテストが可能になる。UIテストの支援をするための仕組みも最近のGHUnitには追加されている。&lt;ul&gt;&lt;li&gt;SenTestingKitの"Logic Test"では想定通りに動作しないUIKitやFoundationのクラスが幾つかあり、中には純粋なロジックで使いそうなクラスも含まれている。そのためSenTestingKitではテストできないロジッククラスが発生する場合があるので、そういう時はGHUnitを使うと良い。&lt;/li&gt;&lt;li&gt;参考: &lt;a href="https://gist.github.com/1662887"&gt;https://gist.github.com/1662887&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;実機上でテストを実行できる。そのため実機でのみ発生するバグをつかまえることが可能。&lt;ul&gt;&lt;li&gt;ただし、実機テストはCUIのテストランナーから実行できないため、Jenkinsと連携することはできない。&lt;/li&gt;&lt;li&gt;参考: &lt;a href="https://github.com/gabriel/gh-unit/issues/13"&gt;https://github.com/gabriel/gh-unit/issues/13&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;SenTestingKitのテストケースをそのまま実行できるため上位互換として使用できる。&lt;/li&gt;&lt;/ul&gt;逆にGHUnitにはSenTestingKitと比べて以下のようなデメリットがあります。&lt;ul&gt;&lt;li&gt;Xcode 4で統合されたUnitTestingの恩恵に預かれない。すなわち&lt;code&gt;Cmd+U&lt;/code&gt;一発でテストケースを実行することができない。Xcode経由だと&lt;code&gt;Cmd+R&lt;/code&gt;でアプリケーションとして起動して、その後起動したアプリのテスト実行ボタンを押す手間が必要になるため、開発のテンポが乱されてしまう。特にTDDを採用している場合には深刻。&lt;/li&gt;&lt;li&gt;上記問題を回避するためCUI経由でテストを実行することもできるのだが、Xcodeのエディタと連携しないため、どこがエラーになっているのかが一目でわかりづらい。&lt;/li&gt;&lt;li&gt;カバレッジの取得が楽。SenTestingKitをシミュレータ上で実行している時が一番やりやすい。&lt;a href="http://akisute.com/2012/01/jenkins-ios-gcov.html"&gt;これについては別の記事で解説します。&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;これを踏まえると、以下のように使い分けができるようになります。&lt;ul&gt;&lt;li&gt;SenTestingKitは純粋なロジックの単体テストを実行したいときに良い。Xcodeからすぐに実行できて一瞬で結果がコード上に出るので、開発のテンポを乱さない。TDDに向いている。&lt;/li&gt;&lt;li&gt;GHUnitは非同期なAPIを持ったクラスの単体テストを実行したいときに良い。またUIApplication, UIWindowといったUIコンポーネントと結合したり、通信やファイルアクセスなどの外部リソースとの結合をおこなった状態でのテストを作る際にも向いている（純粋な単体テストともユーザー受け入れテストとも異なるため、仮に結合テストと呼ぶことにする）ので、そういったものが必要な場合には最高の選択肢となる。&lt;/li&gt;&lt;/ul&gt;プロジェクトの開発方針や開発対象によってどのようなテストが必要になるのかが異なってくると思いますが、どれか1つだけ必要であればGHUnitを選択し、きちんとしたXPでやりたいプロジェクトはSenTestingKitに単体テストをやらせ、ユーザー受け入れテストに &lt;a href="https://github.com/square/KIF"&gt;KIF&lt;/a&gt; などを採用し、その中間を埋める必要があればGHUnitも導入する、というのが良いのではないかと考えています。ちょっと面倒ですけど。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■GHUnitを導入する&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;以下のリポジトリからコードを取得して、XcodeからビルドすればOKです。&lt;br /&gt;&lt;a href="https://github.com/gabriel/gh-unit"&gt;https://github.com/gabriel/gh-unit&lt;/a&gt;&lt;br /&gt;注意点として、GHUnitは.framework版がそのままgithubからダウンロードできるのですが、&lt;br /&gt;&lt;a href="https://github.com/gabriel/gh-unit/issues/69"&gt;https://github.com/gabriel/gh-unit/issues/69&lt;/a&gt;&lt;br /&gt;このような問題が報告されており使えないので、githubからソースコードをクローンしてきて、&lt;pre&gt;cd Project-iOS&lt;br /&gt;make&lt;/pre&gt;でビルドしてできたGHUnitIOS.frameworkを使うようにしてください。&lt;br /&gt;&lt;br /&gt;frameworkをビルドしたら自分のプロジェクトに追加して、GHUnit用のビルドターゲットを作ります。&lt;br /&gt;&lt;a href="http://gabriel.github.com/gh-unit/docs/appledoc_include/guide_install_ios_4.html"&gt;http://gabriel.github.com/gh-unit/docs/appledoc_include/guide_install_ios_4.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;ビルドターゲットができたら、次は試しにテストケースを追加してみて、問題なくテストが走るか確認。&lt;br /&gt;&lt;a href="http://gabriel.github.com/gh-unit/docs/appledoc_include/guide_testing.html"&gt;http://gabriel.github.com/gh-unit/docs/appledoc_include/guide_testing.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;最後にCUI（要するにxcodebuildコマンド経由）でビルドができるようにします。これをやらないとJenkinsと連携できません。&lt;br /&gt;&lt;a href="http://gabriel.github.com/gh-unit/docs/appledoc_include/guide_command_line.html"&gt;http://gabriel.github.com/gh-unit/docs/appledoc_include/guide_command_line.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■OCMockを導入する&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;以下のリポジトリからコードを取得して、XcodeからビルドすればOKです。&lt;br /&gt;&lt;a href="https://github.com/erikdoe/ocmock"&gt;https://github.com/erikdoe/ocmock&lt;/a&gt;&lt;br /&gt;iOS向けビルドはスタティックライブラリ用のビルドしか用意されていませんので、どうしてもフレームワークが良いとこだわる人は頑張ってください＞＜ そうでなければ非常に簡単です。ビルドしたら成果物をそのままプロジェクトに突っ込めばすぐ使えるようになります。&lt;br /&gt;OCMock自体の使い方にはここでは触れませんが、例えば以下のようなテストケースが作れたりします。&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint linenums"&gt;- (void)testOCMock&lt;br /&gt;{&lt;br /&gt;    // Creating a new stub object from class&lt;br /&gt;    {&lt;br /&gt;        id mockedObject = [OCMockObject mockForClass:[NSString class]];&lt;br /&gt;        STAssertThrows([mockedObject length], @"Mocked object raises exception because the fake method is not ready yet.");&lt;br /&gt;        STAssertThrows([mockedObject isKindOfClass:[NSString class]] , @"Mocked object can't even call isKindOfClass: because it's not ready.");&lt;br /&gt;        STAssertFalse([mockedObject class] == [NSString class], @"Mocked object is not a kind of the target class.");&lt;br /&gt;&lt;br /&gt;        [[[mockedObject stub] andCall:@selector(mockedLength) onObject:self] length];&lt;br /&gt;        STAssertEquals([mockedObject length], (NSUInteger)100, @"Mocked object returns the fake value.");&lt;br /&gt;&lt;br /&gt;        [[[mockedObject stub] andReturn:@"AllYourBaseAreBelongToUs"] lowercaseString];&lt;br /&gt;        STAssertEqualObjects([mockedObject lowercaseString], @"AllYourBaseAreBelongToUs", @"Returns mocked value.");&lt;br /&gt;        STAssertEquals([mockedObject length], (NSUInteger)100, @"Previously mocked methods are still valid.");&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // Method Stubbing for existing object&lt;br /&gt;    {&lt;br /&gt;        NSString *stubTargetObject = @"I am a stub target.";&lt;br /&gt;        STAssertEquals([stubTargetObject length], (NSUInteger)19, @"The original implementation of the length method.");&lt;br /&gt;&lt;br /&gt;        id mockedObject = [OCMockObject partialMockForObject:stubTargetObject];&lt;br /&gt;        STAssertTrue([mockedObject isKindOfClass:[NSString class]] , @"Mocked object is a kind of the target class.");&lt;br /&gt;        STAssertEquals([mockedObject length], (NSUInteger)19, @"Mocked object returns the original value.");&lt;br /&gt;&lt;br /&gt;        [[[mockedObject stub] andCall:@selector(mockedLength) onObject:self] length];&lt;br /&gt;        STAssertEquals([mockedObject length], (NSUInteger)100, @"Mocked object returns the fake value.");&lt;br /&gt;        STAssertEquals([stubTargetObject length], (NSUInteger)100, @"Stubbed target object also returns the fake value.");&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;- (NSUInteger)mockedLength&lt;br /&gt;{&lt;br /&gt;    return 100;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■Jenkinsと連携させる&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;最後にJenkins側でビルドターゲットを作りましょう。&lt;br /&gt;&lt;a href="http://gabriel.github.com/gh-unit/docs/appledoc_include/guide_ci.html"&gt;http://gabriel.github.com/gh-unit/docs/appledoc_include/guide_ci.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;こんな感じの設定になると思います。&lt;br /&gt;&lt;div class="separator" style="clear: both;"&gt;&lt;a href="http://2.bp.blogspot.com/-FVNkhelcG64/Tx1LJHP2p-I/AAAAAAAACu8/pKUUVT22GT4/s1600/%25E3%2582%25B9%25E3%2582%25AF%25E3%2583%25AA%25E3%2583%25BC%25E3%2583%25B3%25E3%2582%25B7%25E3%2583%25A7%25E3%2583%2583%25E3%2583%2588%2B2012-01-23%2B20.55.20.png" imageanchor="1" style=""&gt;&lt;img border="0" height="342" width="400" src="http://2.bp.blogspot.com/-FVNkhelcG64/Tx1LJHP2p-I/AAAAAAAACu8/pKUUVT22GT4/s400/%25E3%2582%25B9%25E3%2582%25AF%25E3%2583%25AA%25E3%2583%25BC%25E3%2583%25B3%25E3%2582%25B7%25E3%2583%25A7%25E3%2583%2583%25E3%2583%2588%2B2012-01-23%2B20.55.20.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;あとはいつもどおりジョブを回してみて問題がないか確認すれば完了です。前回ご紹介したようなSenTestKitの単体テストジョブがうまく回っていれば、それをコピーしてきてちょっと設定を変えれば簡単にできるとおもいます。&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-8070796080926080037?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/8070796080926080037/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=8070796080926080037' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/8070796080926080037'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/8070796080926080037'/><link rel='alternate' type='text/html' href='http://akisute.com/2012/01/jenkins-ios-ghunit.html' title='Jenkins を iOS アプリ開発に導入してみた (GHUnit編)'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-oARnNMdBdBE/Tx1LI2oAekI/AAAAAAAACus/aqsLqVaSBKQ/s72-c/%25E3%2582%25B9%25E3%2582%25AF%25E3%2583%25AA%25E3%2583%25BC%25E3%2583%25B3%25E3%2582%25B7%25E3%2583%25A7%25E3%2583%2583%25E3%2583%2588%2B2012-01-23%2B20.55.01.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-75081103599590326</id><published>2012-01-21T20:32:00.003+09:00</published><updated>2012-01-21T20:36:35.566+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iOS 5.0.1'/><category scheme='http://www.blogger.com/atom/ns#' term='テスト'/><category scheme='http://www.blogger.com/atom/ns#' term='Objective-C'/><title type='text'>Objective-C がこの四年間でどれぐらい進化したのか一目でわかるテストケース</title><content type='html'>Twitterに流したら思ったよりも好評でしたので、ブログにも上げておきます。&lt;br /&gt;&lt;br /&gt;こちらがiOS 2地点でのNSURLConnectionクラスを使った非同期通信のテストケース。&lt;br /&gt;&lt;script src="https://gist.github.com/1651089.js?file=AsyncTest_iOS2.m"&gt;&lt;/script&gt;&lt;br /&gt;こちらがiOS 5でのNSURLConnectionクラスを使った非同期通信のテストケース。&lt;br /&gt;&lt;script src="https://gist.github.com/1651089.js?file=AsyncTest_iOS5.m"&gt;&lt;/script&gt;&lt;br /&gt;Blocksはやっぱり偉大です。一つしかテストケースがないうちはまだマシなのですが、これが10個とかになると楽さが全く違ってきます。ぜひためしにURLだけ変えて同じテストケースを10個作ってみてください。iOS 5のBlocksを使ったコードはほとんどコピペだけで終わりますが、iOS 2でのdelegateを使ったコードは他にも変更しなければならない点が多数出てくるはずです。&lt;br /&gt;&lt;br /&gt;また実際にこのコードを走らせてみると、理由はよくわからないのですがiOS 5で追加されたAPIを使ったコード（Blocks)のほうがそうでないコードよりも毎回2倍程度（0.1秒程度）高速に動作しているみたいです。ちょっと謎ですが、新しいAPIにはパフォーマンス面でのメリットもありそうです。GCDのおかげかな？&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-75081103599590326?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/75081103599590326/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=75081103599590326' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/75081103599590326'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/75081103599590326'/><link rel='alternate' type='text/html' href='http://akisute.com/2012/01/objective-c.html' title='Objective-C がこの四年間でどれぐらい進化したのか一目でわかるテストケース'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-3340786003138776489</id><published>2012-01-20T14:30:00.000+09:00</published><updated>2012-01-21T12:01:43.554+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Jenkins'/><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='Xcode'/><category scheme='http://www.blogger.com/atom/ns#' term='Xcode 4.2'/><title type='text'>Jenkins を iOS アプリ開発に導入してみた (SenTestKit編)</title><content type='html'>&lt;div class="separator" style="clear: both;"&gt;&lt;a href="http://4.bp.blogspot.com/-xsX--izQJto/Txj4y3Auo8I/AAAAAAAACt8/NOA82YmVMww/s1600/jenkins-msgpack-objc-build-SimulatorDebug.png" imageanchor="1" style=""&gt;&lt;img border="0" height="285" width="400" src="http://4.bp.blogspot.com/-xsX--izQJto/Txj4y3Auo8I/AAAAAAAACt8/NOA82YmVMww/s400/jenkins-msgpack-objc-build-SimulatorDebug.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;最近、iOSアプリの開発でも継続的インテグレーション(CI)を取り入れていくプロジェクトが増加傾向にあるようで、各種ツールやライブラリ、ノウハウが出回ってきているように感じられます。そこで私も早速iOSアプリ開発でのCI導入を試してみることにしました。今回の導入試験では、以下のような環境を想定して行いました。&lt;ul&gt;&lt;li&gt;iOSアプリの開発を、Xcode 4.X系のプロジェクトとして行う。&lt;/li&gt;&lt;li&gt;VCSにはgitを採用し、githubの公開リポジトリをリポジトリサーバーとして使用する。&lt;/li&gt;&lt;li&gt;CIサーバにはMacを採用し、プロジェクトをビルドするためにXcode 4.Xをインストールしておく。&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■必要なツールを準備する&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;CIといったら、まずは何はなくともJenkinsです。&lt;br /&gt;&lt;a href="http://jenkins-ci.org/"&gt;http://jenkins-ci.org/&lt;/a&gt;&lt;br /&gt;ここでは導入について詳しくは挙げませんが、私は以下の本を参考にしました。&lt;br /&gt;&lt;a href="https://gihyo.jp/dp/ebook/2011/978-4-7741-4952-3"&gt;https://gihyo.jp/dp/ebook/2011/978-4-7741-4952-3&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;続いてJenkinsのプラグインを導入します。&lt;ul&gt;&lt;li&gt;Git &lt;a href="https://wiki.jenkins-ci.org/display/JENKINS/Git+Plugin"&gt;https://wiki.jenkins-ci.org/display/JENKINS/Git+Plugin&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Github &lt;a href="https://wiki.jenkins-ci.org/display/JENKINS/Github+Plugin"&gt;https://wiki.jenkins-ci.org/display/JENKINS/Github+Plugin&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Xcode &lt;a href="https://wiki.jenkins-ci.org/display/JENKINS/Xcode+Plugin"&gt;https://wiki.jenkins-ci.org/display/JENKINS/Xcode+Plugin&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;これでJenkinsの準備はだいたい完了です。&lt;br /&gt;あとはVCSのgitですが、こちらは準備が出来ているという想定で進めます。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■余談:xcodebuildの使い方&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;JenkinsのXcodeプラグインを使えば、自分で面倒なantのbuild.xmlを書いたり、ビルドスクリプトを用意しなくても、JenkinsのGUI上でビルド設定を行うことが出来ますが、念のため基本を理解しておくべく、xcodebuildというツールを使ってみます。xcodebuildはXcodeプロジェクトをCUIからビルドするためのツールで、Xcodeに付属しています。JenkinsのXcodeプラグインも内部的にはこいつを使用しています。&lt;br /&gt;&lt;br /&gt;基本的な使い方の例は以下の通り。&lt;pre&gt;xcodebuild -project MyApp.xcodeproj -configuration Release -target MyApp clean build&lt;br /&gt;xcodebuild -project MyApp.xcodeproj -configuration Debug -target MyAppTests -sdk iphonesimulator5.0 clean build&lt;br /&gt;xcodebuild -project MyApp.xcodeproj -configuration Debug -target MyAppTests -sdk iphonesimulator clean build&lt;/pre&gt;上の例ではデフォルト設定のiOS SDKを用いてビルドターゲットMyAppがReleaseビルドされます。次の例ではiPhone Simulator 5.0 SDKを用いてビルドターゲットMyAppTestsがDebugビルドされます。一番下の例では、手元にある最新のiPhone Simulator SDKが使用されるようです。また -target の代わりに -scheme を使うことも出来ます。ビルドに使うことができるSDKの一覧を得るためには、&lt;pre&gt;xcodebuild -showsdks&lt;/pre&gt;を使えばよいです。&lt;br /&gt;&lt;br /&gt;ビルドアクションにはclean, build以外にもarchiveとかあるのですが試していないので詳細は不明です。しかし残念ながら、少なくともtestアクションがないことは確認しました。そのため、Xcode上で　&lt;code&gt;Cmd+U&lt;/code&gt; を押して実行できる単体テストが、xcodebuild経由では実行できません。これについては後ほどまた触れます。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■Xcodeプロジェクト側の準備&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Jenkinsによる自動化を行うためには、まずはXcodeプロジェクト側を修正して、xcodebuildツールにより単体テストが実行できるような状態にして置かなければなりません。そのため先にXcodeプロジェクト側の設定を修正します。Xcode 4でテストケース付きの新規プロジェクトを作るとテストケース実行用のターゲットが自動的に用意されると思いますが、先述の通りこのターゲットはxcodebuild経由では実行できないため、以下の画像の様にUnit Testing -&gt; Test Hostを削除して対応します。&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both;"&gt;&lt;a href="http://1.bp.blogspot.com/-RQ6iVoiuB1M/Txj53tuM2LI/AAAAAAAACuI/9rWBGV0xCx0/s1600/jenkins-unittest-Xcode-settings.png" imageanchor="1" style=""&gt;&lt;img border="0" height="250" width="400" src="http://1.bp.blogspot.com/-RQ6iVoiuB1M/Txj53tuM2LI/AAAAAAAACuI/9rWBGV0xCx0/s400/jenkins-unittest-Xcode-settings.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;このように設定を変更することで、UIWindowやUIApplicationを使わなければならないテストが実行できなくなりますが、それ以外のテストはXcodeからもxcodebuildからも実行できるようになります。試しにxcodebuildを使ってテストターゲットを実行し、テストが走っていることを確認してください。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■Jenkins側の準備（ジョブの設計）&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;続いていよいよJenkinsの設定に移ります。プラグインは導入してあるので、あとはジョブを作るだけです。Xcode連携のプラグインが入っていれば楽勝です。今回はシミュレータビルドで単体テストを行うので、ビルド後の処理でテスト結果の集約を行い、test-reports/*.xmlを指定しましょう。&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both;"&gt;&lt;a href="http://4.bp.blogspot.com/-UwRs0xo77aw/Txj7bqBrVSI/AAAAAAAACug/xLjFlo8m70U/s1600/msgpack-objc-build-SimulatorDebug%2BConfig%2B%255BJenkins%255D.png" imageanchor="1" style=""&gt;&lt;img border="0" height="400" width="332" src="http://4.bp.blogspot.com/-UwRs0xo77aw/Txj7bqBrVSI/AAAAAAAACug/xLjFlo8m70U/s400/msgpack-objc-build-SimulatorDebug%2BConfig%2B%255BJenkins%255D.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;デバイスビルドでリリース用のビルドを作る場合には、ビルド後の処理でビルド成果物の保存を行い、build/Debug-iphoneos/*.ipa（必要ならdSYMも）などを指定しておけば良いかと思います。デバイスビルドをするにはビルドをするマシンのKeychainにcodesign用の証明書と鍵が格納されている必要があるので注意してください。Technical VersionやMarketing Versionの値を指定すれば、自動的にInfo.plistに指定されているCFBundleVersionやCFBundleVersionShortStringを置換してくれるので非常に便利です。&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both;"&gt;&lt;a href="http://4.bp.blogspot.com/-Qi9xLWbv2-A/Txj7bf3gHxI/AAAAAAAACuU/jhOcE5pE6bg/s1600/msgpack-objc-build-DeviceDebug%2BConfig%2B%255BJenkins%255D.png" imageanchor="1" style=""&gt;&lt;img border="0" height="400" width="283" src="http://4.bp.blogspot.com/-Qi9xLWbv2-A/Txj7bf3gHxI/AAAAAAAACuU/jhOcE5pE6bg/s400/msgpack-objc-build-DeviceDebug%2BConfig%2B%255BJenkins%255D.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;ジョブを作ったら早速実行してみましょう。おそらくビルドだけならあまり苦労せずに通ると思います。私は10回目のビルドで完全に問題なくビルドが回りだすようになりました。&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-3340786003138776489?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/3340786003138776489/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=3340786003138776489' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/3340786003138776489'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/3340786003138776489'/><link rel='alternate' type='text/html' href='http://akisute.com/2012/01/jenkins-ios-sentestkit.html' title='Jenkins を iOS アプリ開発に導入してみた (SenTestKit編)'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-xsX--izQJto/Txj4y3Auo8I/AAAAAAAACt8/NOA82YmVMww/s72-c/jenkins-msgpack-objc-build-SimulatorDebug.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-5226082809267851632</id><published>2012-01-15T17:29:00.000+09:00</published><updated>2012-01-15T17:29:30.831+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C言語'/><category scheme='http://www.blogger.com/atom/ns#' term='デバッグ'/><category scheme='http://www.blogger.com/atom/ns#' term='gdb'/><title type='text'>gdb で void* 型の変数をデバッグする</title><content type='html'>C言語で実装されたライブラリやアプリケーションでは、汎用的な型として随所で void* が使用されますが、これをgdbからデバッグすると、そのままでは型情報が無いためタダのポインタとして扱われてしまいます。これではデバッグ時の都合がよろしくないです。&lt;pre&gt;(gdb) print 0xfee65c0&lt;br /&gt;$1 = 267281856&lt;br /&gt;(gdb) print (void *)0xfee65c0&lt;br /&gt;$2 = (void *) 0xfee65c0&lt;/pre&gt;こんなとき、この void* が指し示している先の型がわかりきっている場合は、その型でキャストしてやって:&lt;pre&gt;(gdb) print (struct imap_session_state_data *)0xfee65c0&lt;br /&gt;$4 = (struct imap_session_state_data *) 0xfee65c0&lt;br /&gt;(gdb) print $4&lt;br /&gt;$5 = (struct imap_session_state_data *) 0xfee65c0&lt;/pre&gt;参照先にアクセスすればきちんと中身が見えます:&lt;pre&gt;(gdb) print * $4&lt;br /&gt;$6 = {&lt;br /&gt;  imap_session = 0xfee6560,&lt;br /&gt;  imap_mailbox = 0xfee6230 "INBOX",&lt;br /&gt;  imap_flags_store = 0xfee6490,&lt;br /&gt;  imap_ssl_callback = 0,&lt;br /&gt;  imap_ssl_cb_data = 0x0&lt;br /&gt;}&lt;br /&gt;(gdb) print $6-&gt;imap_session&lt;br /&gt;$7 = (mailimap *) 0xfee6560&lt;br /&gt;(gdb) print * $7&lt;br /&gt;$8 = {&lt;br /&gt;  imap_response = 0xfee6090 "FETCH completed",&lt;br /&gt;  imap_stream = 0xfeecc90,&lt;br /&gt;  imap_progr_rate = 0,&lt;br /&gt;  imap_progr_fun = 0,&lt;br /&gt;  imap_stream_buffer = 0xfee6a00,&lt;br /&gt;  imap_response_buffer = 0xfee6a20,&lt;br /&gt;  imap_state = 3,&lt;br /&gt;  imap_tag = 4,&lt;br /&gt;  imap_connection_info = 0xfee64d0,&lt;br /&gt;  imap_selection_info = 0xfee6030,&lt;br /&gt;  imap_response_info = 0xfee60e0,&lt;br /&gt;  imap_sasl = {&lt;br /&gt;    sasl_conn = 0x0,&lt;br /&gt;    sasl_server_fqdn = 0x0,&lt;br /&gt;    sasl_login = 0x0,&lt;br /&gt;    sasl_auth_name = 0x0,&lt;br /&gt;    sasl_password = 0x0,&lt;br /&gt;    sasl_realm = 0x0,&lt;br /&gt;    sasl_secret = 0x0&lt;br /&gt;  },&lt;br /&gt;  imap_idle_timestamp = 0,&lt;br /&gt;  imap_idle_maxdelay = 1740,&lt;br /&gt;  imap_body_progress_fun = 0,&lt;br /&gt;  imap_items_progress_fun = 0,&lt;br /&gt;  imap_progress_context = 0x0&lt;br /&gt;}&lt;/pre&gt;これでデバッグがはかどりました。&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-5226082809267851632?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/5226082809267851632/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=5226082809267851632' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/5226082809267851632'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/5226082809267851632'/><link rel='alternate' type='text/html' href='http://akisute.com/2012/01/gdb-void.html' title='gdb で void* 型の変数をデバッグする'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-7899681711398297776</id><published>2012-01-02T16:40:00.000+09:00</published><updated>2012-01-03T00:25:55.025+09:00</updated><title type='text'>2011年のふりかえりなど</title><content type='html'>あけましておめでとうございます。年も開けましたので、2011年のふりかえりをやってみて、2012年の抱負を考えてみたいと思います。&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■やってみたこと&lt;/span&gt;&lt;br /&gt;2010年の途中からiOSアプリの開発担当になったのですが、2011年は始めて一年中iOSアプリの開発に携わることができました。ということでダイジェスト。&lt;ul&gt;&lt;li&gt;１月は前年度から引き続きアプリの修正案件を行なってました。ずいぶんひどく炎上した一年のスタートになったのですが、炎上したプロジェクトでしか学べないものというのはたくさんあるものだと痛感させられました。主に案件がどうして燃えるのかとか、何が死亡フラグか、など。自分一人ではどうにもならないので、急遽助っ人に助けてもらいましてなんとか収拾。助っ人の方々、あの時は本当にありがとうございました＞＜&lt;/li&gt;&lt;li&gt;２月ぐらいから&lt;a href="http://www.beproud.jp/bpr/"&gt;BPR&lt;/a&gt;という自社開発のフレームワークとそれを使ったアプリの開発などをしていました。外部に公開するライブラリを組むのは初めてということで、実に勉強になりました。中身の実装もなかなかうまくいったと思ってます。&lt;/li&gt;&lt;li&gt;その後ちょっとした案件をこなしてましたが、ここでは複数案件の並行進行を余儀なくされたため、またも自分一人ではどうしようもならない事態に。うまい具合にアルバイトの人に仕事をお願いしたりする必要に迫られるなどしました。&lt;/li&gt;&lt;li&gt;５月〜６月が今年一番の正念場でした。それぐらい難しい案件と他の案件を並行で進めていたのですが、ずいぶん自分の設計からミスをしてしまい、自分の限界を知ることになった気がします。主にCore DataまわりとAPI通信実装まわりの限界がこの案件ではっきりと分かりました。それだけではなく、グループで仕事するときの死亡フラグとか、炎上案件の燃え方とか、これまた大いに学ばされました。&lt;/li&gt;&lt;li&gt;７月からはずっと一本のアプリに集中して新規実装および修正を行なっていました。これまでの案件と打って変わってあまりにもサクサク進んだもので、受託開発での「お客さんの力量」の大事さを実感。むしろ自分のほうがお世話になりっぱなしで申し訳ない気持ちでした。この案件では試しにこれまでの社内ライブラリや設計の基本をすべて捨てて新しい方式でやってみたのですが、大いに成功したところもあればひどく失敗したところもあり、結果としてこの挑戦は正解だったと思っています。またとある理由でopensslのコードを読んだりしたなど、より低レイヤーな部分の知識が限定的ながら得られてきました。&lt;/li&gt;&lt;/ul&gt;まとめると、これまでにない難易度のアプリの開発に携われて成長できたのと、自分一人ではどうにもならない場面を何度も経験し、仲間の力の偉大さに気付かされたのが今年の収穫だったと思います。&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■Keep&lt;/span&gt;&lt;br /&gt;去年良かったので続けたかったことはこんなところ。&lt;ul&gt;&lt;li&gt;いろんな技術に手を出す。一年以上積み重ねてきたおかげで、ずいぶんと「一番いいやり方」と思われるiOSアプリの開発手法がわかってきたのですが、その方法に固執するとよりよい方法を見落としたり、時代についていけなくなると思ったのであえて別の方法を試し、結果としてよりよいライブラリやプラクティスを学ぶことができたのが実に良かったので、今年もチャレンジしていきたいところです。またClojureをvの人に薦められてやってみて、これまたずいぶんと刺激を受けたので、良いとされる言語やフレームワークに手を出してみてその設計思想を学び取るのは今年もやっていきたいですね。&lt;/li&gt;&lt;li&gt;積極的に仲間に頼る。去年はずいぶんと仲間のみんなに助けて頂きました＞＜ お陰様でずいぶんとスタンドプレーで無理やり解決しようとしてソウルジェムが濁るようなことがなくなったかと思います。今年も自分以外の周りに視野を広げつつ、困ったときに助けていただけるようにもっと人間的に良い人になりたいなーと思ってます＞＜&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■Problem&lt;/span&gt;&lt;br /&gt;去年よくなかった、またはまだまだ改善の余地があるのはこんなところですかね。&lt;ul&gt;&lt;li&gt;基礎力が足りない。低レイヤーな部分の知識が絶望的に足りない。これはPython温泉の際に指摘されたことで、実に悔しいのですがたしかに通信はHTTPより下のレイヤが殆どわかっておらず、言語はObjective-CがわかってもC/C++がわかってない。アルゴリズムの知識も足りなければ、基本的な数学知識も甘い。&lt;/li&gt;&lt;li&gt;さらなる設計力の向上が必要。ずいぶんとよくはなりましたが、それでもまだライブラリやSDKの実装のために必要なレベルの設計力がまだ不足しているように感じられます。&lt;/li&gt;&lt;li&gt;グループでの開発手法。自分一人の案件というのがほとんどだったので、たまにチーム戦をやるとひどくミスを連発して、見積もりを間違えたりレビュー不足からひどい炎上を招いたりと失敗が続いているため、グループでの開発のやり方を本気で考えなければならないと痛感させられています。&lt;/li&gt;&lt;li&gt;テストの仕方。単体テストと、結合テスト。テストの自動化事態はGHUnitのおかげでずいぶんと進んできたのですが、通信を含んだりファイル操作をするテストが単体テストに紛れ込んでいたりして、自動化の妨げとなっています。SenTestKitとモックを使ったほんとうの意味での単体テストと、それ以外のテストをきちんと分ける開発手法を編み出していきたいです。&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■Try&lt;/span&gt;&lt;br /&gt;ということでそれを踏まえて、今年はこんな感じのことに挑戦したいです。&lt;ul&gt;&lt;li&gt;より低レイヤーな知識の学習。TCP/IPとUDPは必修、できればTCP上でmsgpackあたりのRPCプロトコルを自分で実装できる程度にはなりたいと考えています。CとC++の知識も増やしていきたいです。&lt;/li&gt;&lt;li&gt;グループでの開発手法を学びたいです。あとはコミュ力向上。私は自分勝手で人の話を聞かず一度良いと感じたらその手法を信じこんでやまない（人に押し付ける傾向がある）ので、たとえその手法が実際に良かったとしても、チーム全体になじまずマイナスの影響を及ぼしている可能性があります。そういったことをなくすにはどうするか？ということで複数の開発手法を学ぶというのと、人の話を聞いてそれを採用する、これに尽きるでしょう。&lt;/li&gt;&lt;li&gt;テストの仕方の改善とCIの導入。まずは単体テストの完全自動化と、リリースビルドの日次生成からはじめ、徐々に取得する集計データの量を増やしていく、例えばカバレッジの計測は簡単に思いつきますし、GoogleやMSはバグが発生しやすい箇所を予め計算する方程式を持っているそうで、そういうのを日次で集計できれば全体の品質に寄与できる可能性があります。&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-7899681711398297776?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/7899681711398297776/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=7899681711398297776' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/7899681711398297776'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/7899681711398297776'/><link rel='alternate' type='text/html' href='http://akisute.com/2012/01/2011.html' title='2011年のふりかえりなど'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-8408420676033874506</id><published>2011-12-07T17:29:00.000+09:00</published><updated>2011-12-07T17:29:28.885+09:00</updated><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='github'/><category scheme='http://www.blogger.com/atom/ns#' term='Cocoa'/><title type='text'>CocoaPods に対応していないライブラリを集めた自分用リポジトリを作る方法</title><content type='html'>&lt;div class="separator" style="clear: both;"&gt;&lt;a href="http://a1.twimg.com/profile_images/1617095407/cocoapods_bigger.jpg" imageanchor="1" style=""&gt;&lt;img border="0" height="73" width="73" src="http://a1.twimg.com/profile_images/1617095407/cocoapods_bigger.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;この記事は&lt;a href="http://atnd.org/events/22792"&gt;iOS Advent Calendar 2011&lt;/a&gt;の7日目の記事になります。ということでもうすぐクリスマスですね。クリスマスプレゼントの準備はお済みですか？まだの方はちょっとオシャレに、今年のプレゼントをCocoaPodsでご用意してみてはいかがでしょうか？&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■ご存じ、ないのですか!?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;さて念のためCocoaPodsについておさらい。要するにiOS/OS X用のmavenです。以上。細かい点については以下の記事が詳しいのでそちらをご参照ください。&lt;del&gt;っていうかMac Dev JP Advent Calendarとネタがもろかぶり&lt;/del&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://iphone-dev.g.hatena.ne.jp/laiso/20111117/1321437909"&gt;http://iphone-dev.g.hatena.ne.jp/laiso/20111117/1321437909&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://d.hatena.ne.jp/Watson/20111204/mac_dev_jp_advent_calendar_cocoapods01"&gt;http://d.hatena.ne.jp/Watson/20111204/mac_dev_jp_advent_calendar_cocoapods01&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;このCocoaPodsを使うと今まで大変面倒くさかったライブラリの管理が嘘のように簡単になります。たとえば、新しいプロジェクトを始めるときに、&lt;ul&gt;&lt;li&gt;通信したいからASIHTTPRequestを使おう&lt;/li&gt;&lt;li&gt;APIのレスポンスがJSONだからJSONKitも必要だな&lt;/li&gt;&lt;li&gt;DBにはCore Dataを採用したいから、MagicalRecordも欲しいな&lt;/li&gt;&lt;li&gt;Blocksバリバリ使うからBlocksKitは常識だよね&lt;/li&gt;&lt;/ul&gt;と思ったら、さくっと以下のような設定ファイル（Podfile, mavenで言うところのpom.xml）を書いてやれば、あとはCocoaPodsが指定されたライブラリを取ってきてビルド設定までやってくれるわけです。&lt;pre&gt;platform :ios&lt;br /&gt;&lt;br /&gt;dependency 'ASIHTTPRequest' ,'~&gt; 1.8'&lt;br /&gt;dependency 'JSONKit'        ,'~&gt; 1.4'&lt;br /&gt;dependency 'BlocksKit'&lt;br /&gt;dependency 'MagicalRecord'&lt;/pre&gt;ARCあり・なしのライブラリを混ぜても全く問題ありません。素晴らしい！！&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■公開なんて、あるわけない&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;とまぁ実に素晴らしいツールなのですが、問題もあります。&lt;ul&gt;&lt;li&gt;つい最近できたばかりのツールなので、対応しているライブラリが少ない&lt;/li&gt;&lt;li&gt;対応しているライブラリでも、もともと依存関係処理をするという文化があまりなかったせいか、一部のライブラリ（Reachabilityとか）が内包された状態で出回っていたり、バージョンタグが一つや二つしか付いていないので上手くバージョン管理が出来ない（しかも極端に古かったりバグがあったり、さんざん）&lt;/li&gt;&lt;li&gt;CocoaPods自体が開発途中ということもあり、機能がどんどん追加されているようなのだがドキュメントが追いついていない&lt;/li&gt;&lt;/ul&gt;例を挙げると以下の画像のような感じで、バージョンが一つしかなかったり、あるんだけれど飛んでいたりなどなど。要するに自分の使いたいコードがCocoaPodsの中央リポジトリで管理されていないということがままあります。&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both;"&gt;&lt;a href="http://1.bp.blogspot.com/-DruoVtM9rIY/TttHdOmbnuI/AAAAAAAACtA/tqgnxmb4zQE/s1600/pod_search_wo_siirareteirunda.png" imageanchor="1" style=""&gt;&lt;img border="0" height="305" width="400" src="http://1.bp.blogspot.com/-DruoVtM9rIY/TttHdOmbnuI/AAAAAAAACtA/tqgnxmb4zQE/s400/pod_search_wo_siirareteirunda.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■俺達は、自分たちでpodspecを用意することを......強いられているんだ！&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;ありがたいことに、CocoaPodsには中央リポジトリ以外の任意のリポジトリをライブラリ管理用のリポジトリとして追加する機能があります。この機能を使って、自分で対応していないライブラリのpodspecファイルを書いて、CocoaPodsで使えるようにすることができます。&lt;a href="https://github.com/CocoaPods/CocoaPods/blob/6cf539af4882d2632a20ddc6be7b15d3d31e6c2e/CHANGELOG.md"&gt;またCocoaPods 0.3.0以降であれば、設定ファイルに直接自分の好きなライブラリのpodspecを書くこともできるみたいです。&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;まず最初のステップはpodspecを書くことです。今回は例として&lt;a href="https://github.com/MugunthKumar/MKNetworkKit"&gt;MKNetworkKit&lt;/a&gt;というライブラリのバージョンv0.8a用のpodspecを書いてみることにします。&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;# まずは対象のリポジトリをcloneしてくる&lt;br /&gt;# ここでは相手のリポジトリを直接使ってますが、github上でforkして、そっちを使うようにしてもいいです。forkしたほうが自分で自由にコードに改変を加えたりtagを打ったりできますのでよいかも。&lt;br /&gt;git clone https://github.com/MugunthKumar/MKNetworkKit.git&lt;br /&gt;# 移動&lt;br /&gt;cd MKNetworkKit&lt;br /&gt;# 対象のバージョンにHEADを移動します&lt;br /&gt;git reset --hard v0.8a&lt;br /&gt;# podspecファイルのひな形を出力します&lt;br /&gt;pod spec create MKNetworkKit&lt;/pre&gt;これでMKNetworkKit.podspecファイルが出力されますので、今度はこのファイルを書き換えます。先ほどcloneしてきたライブラリのソースコードとプロジェクト設定を見ながら、必要なソースコード、必要なリソース、不要なファイル、ライブラリやフレームワークなどのビルド設定を考えて、適切な設定を用意しなければなりません。&lt;br /&gt;今回はこんな感じで書きました:&lt;pre&gt;Pod::Spec.new do |s|&lt;br /&gt;  s.name     = 'MKNetworkKit'&lt;br /&gt;  s.version  = '0.8a'&lt;br /&gt;  s.license  = 'MIT'&lt;br /&gt;  s.summary  = 'Full ARC based Networking Kit for iOS 4+ devices'&lt;br /&gt;  s.homepage = 'https://github.com/MugunthKumar/MKNetworkKit'&lt;br /&gt;  s.author   = { 'MugunthKumar' =&gt; 'mknetworkkit@mk.sg' }&lt;br /&gt;  s.source   = { :git =&gt; 'https://github.com/MugunthKumar/MKNetworkKit.git', :tag =&gt; 'v0.8a' }&lt;br /&gt;&lt;br /&gt;  s.source_files = 'MKNetworkKit/*.{h,m}', 'MKNetworkKit/Categories/*.{h,m}'&lt;br /&gt;  s.clean_paths  = 'MKNetworkKitDemo', '*.xcodeproj', 'sample.JPG'&lt;br /&gt;  s.frameworks   = 'CFNetwork'&lt;br /&gt;  s.requires_arc = true&lt;br /&gt;&lt;br /&gt;  s.dependency 'Reachability', '~&gt; 2.0'&lt;br /&gt;end&lt;/pre&gt;大事なのはsource, source_files, frameworks, requires_arc, dependencyぐらいです。あとは自分しか使わないならでたらめでかまいません。&lt;br /&gt;sourceは:tagの指定の代わりに:commitでコミットのハッシュ値を指定することもできるみたいです。&lt;br /&gt;このpodspecファイルの記法、やたらとたくさんある上にドキュメントがあまりないので、私は結局公式リポジトリのpodspecを探して見よう見まねで書きました。以下、参考にした物を列挙します。&lt;br /&gt;&lt;a href="https://github.com/CocoaPods/Specs"&gt;https://github.com/CocoaPods/Specs&lt;/a&gt;&lt;br /&gt;&lt;a href="https://github.com/CocoaPods/Specs/blob/master/ASIHTTPRequest/1.8.1/ASIHTTPRequest.podspec"&gt;https://github.com/CocoaPods/Specs/blob/master/ASIHTTPRequest/1.8.1/ASIHTTPRequest.podspec&lt;/a&gt;&lt;br /&gt;&lt;a href="https://github.com/CocoaPods/Specs/blob/master/ASIWebPageRequest/1.8.1/ASIWebPageRequest.podspec"&gt;https://github.com/CocoaPods/Specs/blob/master/ASIWebPageRequest/1.8.1/ASIWebPageRequest.podspec&lt;/a&gt;&lt;br /&gt;&lt;a href="https://github.com/CocoaPods/Specs/blob/master/BlocksKit/0.5.0/BlocksKit.podspec"&gt;https://github.com/CocoaPods/Specs/blob/master/BlocksKit/0.5.0/BlocksKit.podspec&lt;/a&gt;&lt;br /&gt;&lt;a href="https://github.com/CocoaPods/Specs/blob/master/BlocksKit/0.9.0/BlocksKit.podspec"&gt;https://github.com/CocoaPods/Specs/blob/master/BlocksKit/0.9.0/BlocksKit.podspec&lt;/a&gt;&lt;br /&gt;&lt;a href="https://github.com/CocoaPods/Specs/blob/master/SSToolkit/0.1.2/SSToolkit.podspec"&gt;https://github.com/CocoaPods/Specs/blob/master/SSToolkit/0.1.2/SSToolkit.podspec&lt;/a&gt;&lt;br /&gt;&lt;a href="https://github.com/CocoaPods/Specs/blob/master/Kiwi/1.0.0/Kiwi.podspec"&gt;https://github.com/CocoaPods/Specs/blob/master/Kiwi/1.0.0/Kiwi.podspec&lt;/a&gt;&lt;br /&gt;&lt;a href="https://github.com/CocoaPods/Specs/blob/master/MGSplitViewController/1.0.0/MGSplitViewController.podspec"&gt;https://github.com/CocoaPods/Specs/blob/master/MGSplitViewController/1.0.0/MGSplitViewController.podspec&lt;/a&gt;&lt;br /&gt;使用するリソースファイルも指定出来るみたいです。&lt;br /&gt;&lt;a href="https://github.com/CocoaPods/Specs/blob/master/SVProgressHUD/0.5/SVProgressHUD.podspec"&gt;https://github.com/CocoaPods/Specs/blob/master/SVProgressHUD/0.5/SVProgressHUD.podspec&lt;/a&gt;&lt;br /&gt;巨大なのになるとこんなのも書けるみたいです。&lt;br /&gt;&lt;a href="https://github.com/CocoaPods/Specs/blob/master/RestKit/0.9.3/RestKit.podspec"&gt;https://github.com/CocoaPods/Specs/blob/master/RestKit/0.9.3/RestKit.podspec&lt;/a&gt;&lt;br /&gt;&lt;a href="https://github.com/CocoaPods/Specs/blob/master/Nimbus/0.9.0/Nimbus.podspec"&gt;https://github.com/CocoaPods/Specs/blob/master/Nimbus/0.9.0/Nimbus.podspec&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;書き終わったら、書いたpodspecファイルに問題がないかをチェックします。&lt;pre&gt;pod spec lint MKNetowrkKit.podspec&lt;/pre&gt;何か問題があれば何かエラーが出ます。修正しましょう。何も無ければ何も出ません。&lt;br /&gt;問題が無くなったらひとまずpodspecファイルについては完成です。次はこのpodspecファイルを置くリポジトリをgithubを使って用意します。github上に適当な名前でリポジトリを作りましょう。私は今回 &lt;a href="https://github.com/akisute/Specs"&gt;https://github.com/akisute/Specs&lt;/a&gt; というリポジトリを作りました。&lt;br /&gt;リポジトリを作ったら、先ほど作ったpodspecファイルを、以下の命名規則に従ってリポジトリの中に配置します:&lt;pre&gt;/podspecのs.name/podspecのs.version/先ほど作ったpodspecファイル&lt;/pre&gt;たとえば今回の例では:&lt;pre&gt;/MKNetworkKit/0.8a/MKNetworkKit.podspec&lt;/pre&gt;という名前で配置する必要があります。私が試した際は、間違ってると正しくpodspecファイルを認識してくれませんでした。ファイルを配置したらこのリポジトリをgithubにpushします。&lt;br /&gt;&lt;br /&gt;さてこれでpodspec用のリポジトリが出来ましたので、今度はCocoaPods側の設定を行います。以下のコマンドを実行します:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;pod repo add myrepo リポジトリのURL&lt;/pre&gt;これでmyrepoという名前でリポジトリが登録されます。 &lt;code&gt;~/.cocoapods/&lt;/code&gt; 以下を覗いてみると、確かに myrepo という名前のリポジトリが追加されているはずです。&lt;br /&gt;&lt;br /&gt;あとは普通にCocoaPodsを使うのと同じ要領で、Podfileを書いて、pod installすればうまくいくはずです。・・・といいたいところなのですが、一発でうまくいくことはまれで、たいていpodspecファイルの書き方に問題があったりとか、pod化したい対象のライブラリのコードに問題があってビルドが通らないのが普通です。そこで以下のようなワークフローになります。&lt;ol&gt;&lt;li&gt;コードに問題があるなら、コードをforkして自分の思うように書き換えてpush&lt;/li&gt;&lt;li&gt;podspecファイルを修正して自分のpodspec用リポジトリにpush&lt;/li&gt;&lt;li&gt;組み込みたいプロジェクトのPodsディレクトリ、Podfile.lockファイル、生成されたxcworkspaceを削除。&lt;/li&gt;&lt;li&gt;再度 &lt;code&gt;pod install MyProject.xcodeproj&lt;/code&gt; を実行。&lt;/li&gt;&lt;li&gt;ビルド。&lt;/li&gt;&lt;li&gt;問題があれば1. に戻る。&lt;/li&gt;&lt;/ol&gt;&lt;span style="font-weight:bold; color:#cc0000;"&gt;うん、これは素人にはお勧めできない。&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;しかしながらこのCocoaPodに対応するライブラリが増えていけば、iOSの開発はずいぶんと楽になるはずです。ということで積極的に使っていきたいと思います！&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-8408420676033874506?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/8408420676033874506/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=8408420676033874506' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/8408420676033874506'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/8408420676033874506'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/12/cocoapods.html' title='CocoaPods に対応していないライブラリを集めた自分用リポジトリを作る方法'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-DruoVtM9rIY/TttHdOmbnuI/AAAAAAAACtA/tqgnxmb4zQE/s72-c/pod_search_wo_siirareteirunda.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-2978357083131712714</id><published>2011-11-27T23:11:00.001+09:00</published><updated>2011-11-27T23:21:54.663+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ライブラリ'/><category scheme='http://www.blogger.com/atom/ns#' term='Objective-C'/><category scheme='http://www.blogger.com/atom/ns#' term='Cocoa'/><category scheme='http://www.blogger.com/atom/ns#' term='非同期処理'/><title type='text'>Cocoa Framework に用意されていないロックを Objective-C で実装する</title><content type='html'>&lt;div class="separator" style="clear: both;"&gt;&lt;a href="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6a/Dining_philosophers.png/463px-Dining_philosophers.png" imageanchor="1" style=""&gt;&lt;img border="0" height="480" width="463" src="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6a/Dining_philosophers.png/463px-Dining_philosophers.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Cocoaフレームワークは非同期処理時のロックを取るために、NSLockingというプロトコルと、NSLock, NSRecurrsiveLock, そしてNSConditionalLockという3種類のロックの実装を提供しています。が、残念ながらちょっとまともな非同期コードを書こうと思うとこれでは全然足りません。っていうか、NSConditionalLockがロック抜けるときにしか条件値を書き換えられない実装なのが正直いけてないと思います。これじゃCounting Lock（最初に決めた数だけ同時にロックできるロック。Counting Semaphoreともいう）にもRead/Write Lock（書き込みロックと読み込みロックの二種類が用意され、書き込みロックが取られていない限りは、何個でも同時に読み込みロックが取れる、効率のいいロック）にも使えません。というわけで、Objective-Cで書かれたCounting LockとRead/Write Lockを見つけましたのでご紹介いたします。&lt;br /&gt;&lt;br /&gt;&lt;a href="http://cocoaheads.byu.edu/wiki/locks"&gt;http://cocoaheads.byu.edu/wiki/locks&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;中身はpthread.hのpthread_mutexを使って実装しているようです。一見危なそうですが、Cocoaフレームワークが使用するスレッドは全て内部実装がpthreadなので全く問題ありません。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-2978357083131712714?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/2978357083131712714/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=2978357083131712714' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/2978357083131712714'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/2978357083131712714'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/11/cocoa-framework-objective-c.html' title='Cocoa Framework に用意されていないロックを Objective-C で実装する'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-4818428987492313080</id><published>2011-11-23T17:11:00.001+09:00</published><updated>2011-11-24T23:33:24.402+09:00</updated><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='Xcode 4.2'/><title type='text'>静的ライブラリ中のシグネチャが衝突してビルドできないときに再ビルドしないでシグネチャを書き換える</title><content type='html'>皆さんも以下のようなビルドエラーを見たことが一度はあると思います。&lt;br /&gt;&lt;div class="separator" style="clear: both;"&gt;&lt;a href="http://2.bp.blogspot.com/-fi-rYsHOM5g/Tsyq3JJfUmI/AAAAAAAACso/dQKwKBvvF18/s1600/conflict_between_libraries.png" imageanchor="1" style=""&gt;&lt;img border="0" height="302" width="400" src="http://2.bp.blogspot.com/-fi-rYsHOM5g/Tsyq3JJfUmI/AAAAAAAACso/dQKwKBvvF18/s400/conflict_between_libraries.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;これはビルド時に同一プロジェクト内に同じ名前のシグネチャの関数やクラスが存在するためリンクができなくて失敗しているというエラーです。特に以下のようなケースでよく発生します。&lt;ul&gt;&lt;li&gt;自分が作ったクラスや関数の名前と、外部から持ってきたライブラリが使っているクラスや関数の名前が衝突している&lt;/li&gt;&lt;li&gt;外部から持ってきたライブラリ同士でクラスや関数の名前が衝突している&lt;/li&gt;&lt;li&gt;外部ライブラリをインストールする際に、-all_loadしたり-ObjCしたりている&lt;/li&gt;&lt;/ul&gt;そういうわけで、外部からライブラリをたくさん導入すると、base64やMD5など、プログラム上でよく使われるのに標準で用意されていないライブラリがよく衝突してしまうわけです。大抵の場合はぶつかっているシグネチャの名前をソースコード上でちょっと書き換えて再度ビルドすることで回避ができるのですが、極稀にソースコードを書き換えることができないケースが存在します。以下にそんな場合の対処方法をまとめます。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■具体例&lt;/span&gt;&lt;br /&gt;AdMobのSDK(libGoogleAdMob.a)とopenssl(libcrypto.a)を同時に一つのプロジェクトにインストールした時、冒頭の画像のようにMD5というシグネチャがビルド時に衝突してしまうのです。AdMobのはプロプロエタリなので当然書き換えられませんし、opensslのように巨大で複雑なコードに手を入れて再ビルドするのも非常に危険です。そもそもopensslはビルド自体が難しいのです。&lt;br /&gt;&lt;br /&gt;このような場合は、ソースコード自体を書き換えるのではなくビルド済みの静的ライブラリ側のオブジェクトファイルを書き換えることで対処を行うことが可能です。&lt;br /&gt;コンパイル時のリンカの設定を変更すれば対処できそうな気もするんですが、GNU ldにはそのようなオプションが見当たりませんでした。なんかSun Solarisのldだと対処できるみたいです。&lt;br /&gt;参考: &lt;a href="http://stackoverflow.com/questions/6940384/how-to-deal-with-symbol-collisions-between-statically-linked-libraries"&gt;http://stackoverflow.com/questions/6940384/how-to-deal-with-symbol-collisions-between-statically-linked-libraries&lt;/a&gt;&lt;br /&gt;参考: &lt;a href="http://stackoverflow.com/questions/393980/restricting-symbols-in-a-linux-static-library"&gt;http://stackoverflow.com/questions/393980/restricting-symbols-in-a-linux-static-library&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; color:#cc0000;"&gt;注意: 以下の手順は失敗すると静的ライブラリ自体が完全に破損したり、実行時に深刻な問題が発生する可能性があります！！&lt;/span&gt; 以下の解説を見てもちんぷんかんぷんな人は適用しないことを強くおすすめいたします。この手順を適用したことによって発生したいかなる損害についても私は責任をとりかねます。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■静的ライブラリ内部のシグネチャを書き換える方法&lt;/span&gt;&lt;br /&gt;静的ライブラリ内部のシグネチャを書き換えるには、以下のようなツールを使用します。&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;lipo&lt;/span&gt;&lt;br /&gt;以前にもご紹介した、Apple純正のユニバーサルバイナリ/ユニバーサルライブラリ(fat binaryともいいます)を作ったりバラしたりするツールです。iOSのライブラリはほぼすべてがi386, armv6, armv7の三種類に対応するfat binaryになっており、基本的にApple純正でないツールはそういったfat binaryに対して歯が立たないので、まずこのツールを使って普通のライブラリに戻した上で、以下のツールを使うわけです。&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;nm&lt;/span&gt;&lt;br /&gt;こいつもApple純正です。バイナリの中に入っているシグネチャの名前を一覧表示することができます。Apple純正なのでfat binaryに対しても使えて超便利です。&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;objdump&lt;/span&gt;&lt;br /&gt;GNU objdumpというツールがありまして、こいつを使うとバイナリの詳細な中身を覗き見ることができます。nmよりも表示される情報が詳細です。Apple純正ではないので、以下で紹介されているようにしてMacPorts経由でインストールするのをお勧めします。&lt;br /&gt;&lt;a href="http://d.hatena.ne.jp/amachang/20080401/1207027290"&gt;http://d.hatena.ne.jp/amachang/20080401/1207027290&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;objcopy&lt;/span&gt;&lt;br /&gt;GNU objcopyです。ライブラリ内部のシグネチャを書き換える事ができるツールで、objdumpとセットでついてくるのですが、残念ながらiOS向けのバイナリに対しては全く使えません。話すと長くなるのですがバージョンを変えようがarm向けのセットをインストールしようがarでライブラリからオブジェクトファイルを取り出して試みてみようが何やっても一切無駄です。使えませんので諦めてください。&lt;br /&gt;参考: &lt;a href="http://www.mail-archive.com/bug-binutils@gnu.org/msg02829.html"&gt;http://www.mail-archive.com/bug-binutils@gnu.org/msg02829.html&lt;/a&gt;&lt;br /&gt;参考: &lt;a href="http://stackoverflow.com/questions/2231698/how-can-i-easily-install-arm-elf-gcc-on-os-x"&gt;http://stackoverflow.com/questions/2231698/how-can-i-easily-install-arm-elf-gcc-on-os-x&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;objconv&lt;/span&gt;&lt;br /&gt;で、使えないobjcopyに代わって、今回の英雄です。こいつを使って実際にライブラリ内部のシグネチャを自由自在に書き換えることができます。メンテもしっかり行われているようで動作も安定しています。以下のサイトからダウンロードできます。&lt;br /&gt;サイト: &lt;a href="http://www.agner.org/optimize/#objconv"&gt;http://www.agner.org/optimize/#objconv&lt;/a&gt;&lt;br /&gt;マニュアル: &lt;a href="http://www.agner.org/optimize/objconv-instructions.pdf"&gt;http://www.agner.org/optimize/objconv-instructions.pdf&lt;/a&gt;&lt;br /&gt;残念ながらsource配布のみしか無いため、自分でビルドしてやる必要があります。と言ってもそこそこ簡単で、以下のようにするだけです。&lt;ul&gt;&lt;li&gt;ソースコードをダウンロードする&lt;/li&gt;&lt;li&gt;zipを解凍する&lt;/li&gt;&lt;li&gt;source.zipを解凍する&lt;/li&gt;&lt;li&gt;build.shを実行する。ただしこのシェルスクリプトは1行目だけがひどくバグってるので、自分で中を見てビルドコマンドを叩いてやるようにしてください。ね？簡単でしょう？&lt;/li&gt;&lt;/ul&gt;さて、これで実際にシグネチャの書き換えを行う準備が整いました。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■実践:全く同一のライブラリのシグネチャだった場合&lt;/span&gt;&lt;br /&gt;base64なんかでよく発生します。この場合は片方をweakシンボルにします。&lt;br /&gt;weakシンボルとは: &lt;a href="http://d.hatena.ne.jp/syohex/20100610/1276180481"&gt;http://d.hatena.ne.jp/syohex/20100610/1276180481&lt;/a&gt; がわかりやすいです。&lt;br /&gt;&lt;br /&gt;早速やってみましょう。以下の例ではlibTest.a中のbase64_encodeシグネチャを書き換えます。&lt;br /&gt;まずは以下のコマンドで対象のライブラリのfat binaryを通常のバイナリに戻して:&lt;pre&gt;lipo -thin armv6 libTest.a -output libTest_armv6.a&lt;br /&gt;lipo -thin armv7 libTest.a -output libTest_armv7.a&lt;br /&gt;lipo -thin i386 libTest.a -output libTest_i386.a&lt;/pre&gt;objconvを実行:&lt;pre&gt;objconv -fmacho -nw:base64_encode libTest_armv6.a&lt;br /&gt;objconv -fmacho -nw:base64_encode libTest_armv7.a&lt;br /&gt;objconv -fmacho -nw:base64_encode libTest_i386.a&lt;/pre&gt;lipoで元通りに戻します:&lt;pre&gt;lipo -create libTest_i386.a libTest_armv6.a libTest_armv7.a -output libTest.a&lt;/pre&gt;これでビルドが通るはずです。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■実践:同じ名前の違うライブラリのシグネチャだった場合&lt;/span&gt;&lt;br /&gt;冒頭のMD5のケースがこれです。名前が同じなのに実装がまるで違うので、weakシンボルにすると深刻なバグが発生します。こういう時は慎重に見定めた上で、使われていないと思われる方のシグネチャをhiddenシンボル（ローカルシンボル）にして、外部ファイルからリンクできないようにしてしまいます。これなら実装は存在しますがリンクされないようになるだけなので、対象のシンボルが外部から使われていないのであればこれだけでいけます。&lt;br /&gt;&lt;br /&gt;今度はlibcrypto.a中の_MD5シグネチャを書き換えてみましょう。&lt;br /&gt;こちらもまずはlipoを使って通常のバイナリに戻して:&lt;pre&gt;lipo -thin armv6 libcrypto.a -output libcrypto_armv6.a&lt;br /&gt;lipo -thin armv7 libcrypto.a -output libcrypto_armv7.a&lt;br /&gt;lipo -thin i386 libcrypto.a -output libcrypto_i386.a&lt;/pre&gt;objconvを実行:&lt;pre&gt;objconv -fmacho -nl:_MD5 libcrypto_armv6.a&lt;br /&gt;objconv -fmacho -nl:_MD5 libcrypto_armv7.a&lt;br /&gt;objconv -fmacho -nl:_MD5 libcrypto_i386.a&lt;/pre&gt;lipoで元通りにして完成:&lt;pre&gt;lipo -create libcrypto_i386.a libcrypto_armv6.a libcrypto_armv7.a -output libcrypto.a&lt;/pre&gt;これで無事ビルドが通りました。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■実践:同じ名前の違うライブラリのシグネチャで、かつ外からバリバリ呼ばれていた場合&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both;"&gt;&lt;a href="http://2.bp.blogspot.com/-3k4iqf59OWU/Tsyq3Zh6osI/AAAAAAAACs0/xIVdS-Gkz6s/s1600/201005222111124ca.jpg" imageanchor="1" style=""&gt;&lt;img border="0" height="306" width="400" src="http://2.bp.blogspot.com/-3k4iqf59OWU/Tsyq3Zh6osI/AAAAAAAACs0/xIVdS-Gkz6s/s400/201005222111124ca.jpg" /&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/42067579805640535-4818428987492313080?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/4818428987492313080/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=4818428987492313080' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/4818428987492313080'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/4818428987492313080'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/11/blog-post.html' title='静的ライブラリ中のシグネチャが衝突してビルドできないときに再ビルドしないでシグネチャを書き換える'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-fi-rYsHOM5g/Tsyq3JJfUmI/AAAAAAAACso/dQKwKBvvF18/s72-c/conflict_between_libraries.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-7262378898376829064</id><published>2011-11-19T17:25:00.001+09:00</published><updated>2011-11-24T23:30:57.663+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iOS 5.0.1'/><category scheme='http://www.blogger.com/atom/ns#' term='iPhone'/><category scheme='http://www.blogger.com/atom/ns#' term='iOS 4.0'/><category scheme='http://www.blogger.com/atom/ns#' term='Cocoa'/><category scheme='http://www.blogger.com/atom/ns#' term='UI'/><title type='text'>UIWebView.scrollView に対して KVO を使うと色々面白い</title><content type='html'>iOS 5より、UIWebViewにscrollViewプロパティが追加され、たとえばスクロールを無効にしたりステータスバーをタップしても一番上に戻らないようにしたりなど、UIWebViewのスクロール周りの処理を外から自由に触れるようになりました。ですが便利なのはこれだけではありません。KVOの仕組みを使うことで、さらにUIWebViewを便利に使うことができます。ここでは私が使っている中で一番のおすすめをご紹介します。&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■UIWebViewの描画しているHTMLのcontentSizeを非同期的に、リアルタイムで取得する&lt;/span&gt;&lt;br /&gt;UIWebview.scrollViewのcontentSizeプロパティは、UIWebViewの描画しているHTMLの大きさ（contentSize）と同じ値になります。この性質を利用して、contentSizeプロパティにKVOを貼ると、UIWebViewの描画しているHTMLの大きさ（contentSize）が変わったタイミングで通知を受け取ることができます。こんなコードになります。&lt;pre class="prettyprint linenums"&gt;- (void)viewWillAppear:(BOOL)animated&lt;br /&gt;{&lt;br /&gt;  [self.webView.scrollView addObserver:self forKeyPath:@"contentSize" options:0 context:NULL];&lt;br /&gt;  [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://akisute.com"]]];&lt;br /&gt;}&lt;br /&gt;- (void)viewWillDisappear:(BOOL)animated&lt;br /&gt;{&lt;br /&gt;  [self.webView.scrollView removeObserver:self forKeyPath:@"contentSize"];&lt;br /&gt;}&lt;br /&gt;- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context&lt;br /&gt;{&lt;br /&gt;  NSLog(@"%s", __func__);&lt;br /&gt;  NSLog(@"  * contentSize = %@", NSStringFromCGRect(self.webView.scrollView.contentSize));&lt;br /&gt;}&lt;/pre&gt;このテクを使うことで、例えばUIWebView自体をスクロールさせないようにした上で通知を受け取ってUIWebViewのframeをどんどん更新するようにし、UIScrollViewの中に埋め込んでしまってUIImageViewやUILabelのようにして使うみたいなUIを作ることが簡単にできます。HTMLの高さに依存するコードも作れますし、なかなか面白いですよ。iOS 5はもちろん、iOS 4でも動作します。（余談で解説）&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■余談&lt;/span&gt;&lt;br /&gt;UIWebViewのscrollViewプロパティは実はiOS 4のころからPrivate APIとして存在します。ですがiOS 5よりパブリック扱いになったおかげか、iOS 4向けのアプリでscrollViewプロパティを触っていてもリジェクトされたりクラッシュすることなく普通に使えるので非常に嬉しいです。iOS 3では使えませんのであしからず。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-7262378898376829064?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/7262378898376829064/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=7262378898376829064' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/7262378898376829064'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/7262378898376829064'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/11/uiwebviewscrollview-kvo.html' title='UIWebView.scrollView に対して KVO を使うと色々面白い'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-8325962362851811811</id><published>2011-11-19T16:17:00.001+09:00</published><updated>2011-11-24T23:30:24.006+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SSL'/><category scheme='http://www.blogger.com/atom/ns#' term='iPhone'/><category scheme='http://www.blogger.com/atom/ns#' term='iPad'/><category scheme='http://www.blogger.com/atom/ns#' term='Cocoa'/><category scheme='http://www.blogger.com/atom/ns#' term='エラー'/><title type='text'>iOS 5でのSSL/TLS通信時にエラーが発生した場合のエラーコードの調べ方</title><content type='html'>iOS 5より新たにSecurity.frameworkというフレームワークが追加されました。このフレームワークはAppleが実装したSSL/TLS用のライブラリで、iOS 5よりCFNetwork系のクラス（NSURLConnectionなどの内部実装にも使われています）のSSL/TLS通信時に使われるようになったみたいです。&lt;br /&gt;&lt;br /&gt;&lt;a href="http://developer.apple.com/library/ios/#releasenotes/General/WhatsNewIniPhoneOS/Articles/iOS5.html"&gt;http://developer.apple.com/library/ios/#releasenotes/General/WhatsNewIniPhoneOS/Articles/iOS5.html&lt;/a&gt; の一番下にちょこっとだけ説明があるので、見てみると、&lt;blockquote&gt;Security&lt;br /&gt;The Security framework (Security.framework) now includes the Secure Transport interfaces, which are Apple’s implementation of the SSL/TLS protocols. You can use these interfaces to configure and manage SSL sessions, manage ciphers, and manage certificates.&lt;br /&gt;&lt;br /&gt;For information about the Secure Transport interfaces, see the SecureTransport.h header file of the Security framework.&lt;/blockquote&gt;うむ、ドキュメント無いからヘッダ読めとはなかなか適当ですね。&lt;br /&gt;&lt;br /&gt;普通にアプリを作っている最中にこのSecurity.frameworkを直接触る必要は全くないのですが、問題はこのSecurity.frameworkを使っているAppleのframeworkが通信時にSSL/TLS絡みのエラーを吐いたときに発生します。このとき、それらのフレームワークは以下のようなNSErrorを返してきます。&lt;pre&gt;Error Domain=NSOSStatusErrorDomain Code=-9830 "The operation couldn’t be completed. (OSStatus error -9830.)&lt;/pre&gt;NSErrorの読み方はErrorDomainに指定されている文字列に応じてエラー番号が定義されているドキュメント/ヘッダファイルを見るというものなのですが、このNSErrorはNSOSStatusErrorDomainのErrorDomainを指定しているにも関わらず&lt;a href="http://opensource.apple.com/source/CarbonHeaders/CarbonHeaders-18.1/MacErrors.h"&gt;&amp;lt;CarbonCore/MacErrors.h&amp;gt;&lt;/a&gt;にエラー番号の定義が全く書いていないのです！&lt;br /&gt;&lt;br /&gt;色々原因を調べた結果、以下のQ&amp;Aが見当たりました。&lt;br /&gt;&lt;a href="http://developer.apple.com/library/mac/#qa/qa1499/_index.html"&gt;http://developer.apple.com/library/mac/#qa/qa1499/_index.html&lt;/a&gt;&lt;br /&gt;どうやらSecurity.framework絡みのエラーはNSOSStatusErrorDomainを使っているがMacErrors.hではなく&amp;lt;Security/SecureTransport.h&amp;gt;などに定義が書いてあるみたいなのです。見てみると・・・&lt;pre class="prettyprint linenum"&gt;/*************************************************&lt;br /&gt; *** OSStatus values unique to SecureTransport ***&lt;br /&gt; *************************************************/&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;    Note: the comments that appear after these errors are used to create SecErrorMessages.strings.&lt;br /&gt;    The comments must not be multi-line, and should be in a form meaningful to an end user. If&lt;br /&gt;    a different or additional comment is needed, it can be put in the header doc format, or on a&lt;br /&gt;    line that does not start with errZZZ.&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;enum {&lt;br /&gt; errSSLProtocol    = -9800, /* SSL protocol error */&lt;br /&gt; errSSLNegotiation   = -9801, /* Cipher Suite negotiation failure */&lt;br /&gt; errSSLFatalAlert   = -9802, /* Fatal alert */&lt;br /&gt; errSSLWouldBlock   = -9803, /* I/O would block (not fatal) */&lt;br /&gt;    errSSLSessionNotFound   = -9804, /* attempt to restore an unknown session */&lt;br /&gt;    errSSLClosedGraceful   = -9805, /* connection closed gracefully */&lt;br /&gt;    errSSLClosedAbort    = -9806, /* connection closed via error */&lt;br /&gt;    errSSLXCertChainInvalid  = -9807, /* invalid certificate chain */&lt;br /&gt;    errSSLBadCert    = -9808, /* bad certificate format */&lt;br /&gt; errSSLCrypto    = -9809, /* underlying cryptographic error */&lt;br /&gt; errSSLInternal    = -9810, /* Internal error */&lt;br /&gt; errSSLModuleAttach   = -9811, /* module attach failure */&lt;br /&gt;    errSSLUnknownRootCert  = -9812, /* valid cert chain, untrusted root */&lt;br /&gt;    errSSLNoRootCert   = -9813, /* cert chain not verified by root */&lt;br /&gt; errSSLCertExpired   = -9814, /* chain had an expired cert */&lt;br /&gt; errSSLCertNotYetValid  = -9815, /* chain had a cert not yet valid */&lt;br /&gt; errSSLClosedNoNotify  = -9816, /* server closed session with no notification */&lt;br /&gt; errSSLBufferOverflow  = -9817, /* insufficient buffer provided */&lt;br /&gt; errSSLBadCipherSuite  = -9818, /* bad SSLCipherSuite */&lt;br /&gt; &lt;br /&gt; /* fatal errors detected by peer */&lt;br /&gt; errSSLPeerUnexpectedMsg  = -9819, /* unexpected message received */&lt;br /&gt; errSSLPeerBadRecordMac  = -9820, /* bad MAC */&lt;br /&gt; errSSLPeerDecryptionFail = -9821, /* decryption failed */&lt;br /&gt; errSSLPeerRecordOverflow = -9822, /* record overflow */&lt;br /&gt; errSSLPeerDecompressFail = -9823, /* decompression failure */&lt;br /&gt; errSSLPeerHandshakeFail  = -9824, /* handshake failure */&lt;br /&gt; errSSLPeerBadCert   = -9825, /* misc. bad certificate */&lt;br /&gt; errSSLPeerUnsupportedCert = -9826, /* bad unsupported cert format */&lt;br /&gt; errSSLPeerCertRevoked  = -9827, /* certificate revoked */&lt;br /&gt; errSSLPeerCertExpired  = -9828, /* certificate expired */&lt;br /&gt; errSSLPeerCertUnknown  = -9829, /* unknown certificate */&lt;br /&gt; errSSLIllegalParam   = -9830, /* illegal parameter */&lt;br /&gt; errSSLPeerUnknownCA   = -9831, /* unknown Cert Authority */&lt;br /&gt; errSSLPeerAccessDenied  = -9832, /* access denied */&lt;br /&gt; errSSLPeerDecodeError  = -9833, /* decoding error */&lt;br /&gt; errSSLPeerDecryptError  = -9834, /* decryption error */&lt;br /&gt; errSSLPeerExportRestriction = -9835, /* export restriction */&lt;br /&gt; errSSLPeerProtocolVersion = -9836, /* bad protocol version */&lt;br /&gt; errSSLPeerInsufficientSecurity = -9837, /* insufficient security */&lt;br /&gt; errSSLPeerInternalError  = -9838, /* internal error */&lt;br /&gt; errSSLPeerUserCancelled  = -9839, /* user canceled */&lt;br /&gt; errSSLPeerNoRenegotiation = -9840, /* no renegotiation allowed */&lt;br /&gt;&lt;br /&gt; /* non-fatal result codes */&lt;br /&gt; errSSLPeerAuthCompleted     = -9841,    /* peer cert is valid, or was ignored if verification disabled*/&lt;br /&gt; errSSLClientCertRequested = -9842, /* server has requested a client cert */&lt;br /&gt;&lt;br /&gt; /* more errors detected by us */&lt;br /&gt; errSSLHostNameMismatch  = -9843, /* peer host name mismatch */&lt;br /&gt; errSSLConnectionRefused  = -9844, /* peer dropped connection before responding */&lt;br /&gt; errSSLDecryptionFail  = -9845, /* decryption failure */&lt;br /&gt; errSSLBadRecordMac   = -9846, /* bad MAC */&lt;br /&gt; errSSLRecordOverflow  = -9847, /* record overflow */&lt;br /&gt; errSSLBadConfiguration  = -9848, /* configuration error */&lt;br /&gt; errSSLLast     = -9849, /* end of range, to be deleted */&lt;br /&gt;&lt;br /&gt;    /* DEPRECATED aliases for errSSLPeerAuthCompleted */&lt;br /&gt;    errSSLServerAuthCompleted   = -9841, /* server cert is valid, or was ignored if verification disabled DEPRECATED */&lt;br /&gt; errSSLClientAuthCompleted   = -9841,    /* client cert is valid, or was ignored if verification disabled; reusing error as you can only be client or server - DEPRECATED */&lt;br /&gt;&lt;br /&gt;};&lt;/pre&gt;ばっちり書いてますね。これでエラーの原因も特定できます。今回のケースはerrSSLIllegalParamだったみたいですね。&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-8325962362851811811?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/8325962362851811811/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=8325962362851811811' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/8325962362851811811'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/8325962362851811811'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/11/ios-5ssltls.html' title='iOS 5でのSSL/TLS通信時にエラーが発生した場合のエラーコードの調べ方'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-8843637828535490127</id><published>2011-11-18T19:09:00.001+09:00</published><updated>2011-11-24T23:29:16.764+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iOS 5.0.1'/><category scheme='http://www.blogger.com/atom/ns#' term='iOS 3.1.3'/><category scheme='http://www.blogger.com/atom/ns#' term='iPhone'/><category scheme='http://www.blogger.com/atom/ns#' term='iPad'/><category scheme='http://www.blogger.com/atom/ns#' term='iOS 4.0'/><title type='text'>iOS 5の日本語キーボードの高さに対応する (iOS 3, 4, 5全対応)</title><content type='html'>iOS 5より日本語キーボードの高さが変わっているので、今まで決め打ちで高さ216pxとかやってレイアウトしていたビューが軒並み使えなくなってしまいました。今後はキーボードが出たり引っ込んだり種類が切り替わったりのタイミングできちんとキーボードの大きさを調べて適切にビューをレイアウトしてやる必要があります。ということでその対応をしたのでメモ。&lt;br /&gt;&lt;br /&gt;前提条件として、以下の要件を満たすように作りました。&lt;ul&gt;&lt;li&gt;iOS 3, 4, 5全てで正常に動作すること。iOS 3.0でも動作しなければならない。&lt;/li&gt;&lt;li&gt;キーボードのframeを適切に取得できること&lt;/li&gt;&lt;li&gt;キーボードが出てくるタイミング、消えるタイミング、キーボードの種類が変わるタイミング、全て取れること&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■まずはログを見てみる&lt;/span&gt;&lt;br /&gt;キーボードの動作のタイミング、およびキーボードのframeは、NSNotificationを使って取得することができます。使用するNotification名はUIWindowのドキュメントに以下のように定義されています。&lt;br /&gt;&lt;a href="http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIWindow_Class/UIWindowClassReference/UIWindowClassReference.html"&gt;http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIWindow_Class/UIWindowClassReference/UIWindowClassReference.html&lt;/a&gt;&lt;pre&gt;// Available from iOS 2&lt;br /&gt;UIKeyboardWillShowNotification&lt;br /&gt;UIKeyboardDidShowNotification&lt;br /&gt;UIKeyboardWillHideNotification&lt;br /&gt;UIKeyboardDidHideNotification&lt;br /&gt;// Available from iOS 5&lt;br /&gt;UIKeyboardWillChangeFrameNotification&lt;br /&gt;UIKeyboardDidChangeFrameNotification&lt;/pre&gt;で、これらのNotification名でNSNotificationCenterにobserverを追加すると、通知が飛んできます。飛んできたNSNotificationオブジェクトのuserInfoプロパティに特定のキーでキーボードのframeが格納されているというしくみです。使えるキーは以下のとおり。&lt;pre&gt;// Available from iOS 3.2&lt;br /&gt;UIKeyboardFrameBeginUserInfoKey&lt;br /&gt;UIKeyboardFrameEndUserInfoKey&lt;br /&gt;// Available from iOS 3.0&lt;br /&gt;UIKeyboardAnimationCurveUserInfoKey&lt;br /&gt;UIKeyboardAnimationDurationUserInfoKey&lt;br /&gt;// Available from iOS 2.0 ~ 3.2 (Deprecated in newer versions)&lt;br /&gt;UIKeyboardCenterBeginUserInfoKey&lt;br /&gt;UIKeyboardCenterEndUserInfoKey&lt;br /&gt;UIKeyboardBoundsUserInfoKey&lt;/pre&gt;iOS 3, 4, 5すべてできちんと動作しなければならないので、これらをふまえて、以下のように実装します。&lt;ul&gt;&lt;li&gt;Notification名にはUIKeyboardWillShowNotification, UIKeyboardDidShowNotification, UIKeyboardWillHideNotification, UIKeyboardDidHideNotificationを使う。&lt;/li&gt;&lt;li&gt;userInfoのキーには、iOS 3.0/3.1のみUIKeyboardBoundsUserInfoKeyを使い、それ以外のバージョンではUIKeyboardFrameEndUserInfoKeyを使う。&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■実装してみる&lt;/span&gt;&lt;br /&gt;ということでまずはサンプルアプリを作って動かしてみて、実際に動作を見てみることにしました。大体こんな感じのコードです。&lt;pre class="prettyprint linenums"&gt;- (void)viewWillAppear:(BOOL)animated&lt;br /&gt;{&lt;br /&gt;  // Notification observerを追加する&lt;br /&gt;  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onUIKeyboardWillShowNotification:) name:UIKeyboardWillShowNotification object:nil];&lt;br /&gt;  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onUIKeyboardDidShowNotification:) name:UIKeyboardDidShowNotification object:nil];&lt;br /&gt;  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onUIKeyboardWillHideNotification:) name:UIKeyboardWillHideNotification object:nil];&lt;br /&gt;  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onUIKeyboardDidHideNotification:) name:UIKeyboardDidHideNotification object:nil];&lt;br /&gt;}&lt;br /&gt;- (void)viewWillDisappear:(BOOL)animated&lt;br /&gt;{&lt;br /&gt;  // Notification observerを削除する&lt;br /&gt;  [[NSNotificationCenter defaultCenter] removeObserver:self];&lt;br /&gt;}&lt;br /&gt;- (void)onUIKeyboardWillShowNotification:(NSNotification *)notification&lt;br /&gt;{&lt;br /&gt;  NSLog(@"%s", __func__);&lt;br /&gt;  NSLog(@"  * userInfo = %@", notification.userInfo);&lt;br /&gt;  // UIKeyboardFrameEndUserInfoKeyが使える時と使えない時で処理を分ける&lt;br /&gt;  CGRect bounds;&lt;br /&gt;  if (&amp;UIKeyboardFrameEndUserInfoKey == NULL) {&lt;br /&gt;    // iOS 3.0 or 3.1&lt;br /&gt;    // bounds&lt;br /&gt;    bounds = [[notification.userInfo objectForKey:UIKeyboardBoundsUserInfoKey] CGRectValue];&lt;br /&gt;  } else {&lt;br /&gt;    // それ以外&lt;br /&gt;    // frameだがoriginを使わないのでbounds扱いで良い&lt;br /&gt;    bounds = [[notification.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];&lt;br /&gt;  }&lt;br /&gt;  // boundsを使った処理をここに書く&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;ログはこんな感じに。&lt;br /&gt;&lt;br /&gt;iOS 5.0, iPhone 4S&lt;pre&gt;2011-10-19 10:35:15.007 SampleApp[5675:707] -[SampleViewController viewWillAppear:]&lt;br /&gt;// 前の画面の英字キーボードが一旦引っ込んで出てきている&lt;br /&gt;2011-10-19 10:35:15.502 SampleApp[5675:707] -[SampleViewController onUIKeyboardDidHideNotification:]&lt;br /&gt;2011-10-19 10:35:15.506 SampleApp[5675:707]   * userInfo = {&lt;br /&gt;    UIKeyboardAnimationCurveUserInfoKey = 0;&lt;br /&gt;    UIKeyboardAnimationDurationUserInfoKey = "0.25";&lt;br /&gt;    UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {320, 216}}";&lt;br /&gt;    UIKeyboardCenterBeginUserInfoKey = "NSPoint: {160, 372}";&lt;br /&gt;    UIKeyboardCenterEndUserInfoKey = "NSPoint: {160, 588}";&lt;br /&gt;    UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 264}, {320, 216}}";&lt;br /&gt;    UIKeyboardFrameChangedByUserInteraction = 0;&lt;br /&gt;    UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 480}, {320, 216}}";&lt;br /&gt;}&lt;br /&gt;2011-10-19 10:35:15.509 SampleApp[5675:707] -[SampleViewController onUIKeyboardWillShowNotification:]&lt;br /&gt;2011-10-19 10:35:15.510 SampleApp[5675:707]   * userInfo = {&lt;br /&gt;    UIKeyboardAnimationCurveUserInfoKey = 0;&lt;br /&gt;    UIKeyboardAnimationDurationUserInfoKey = "0.35";&lt;br /&gt;    UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {320, 216}}";&lt;br /&gt;    UIKeyboardCenterBeginUserInfoKey = "NSPoint: {160, 372}";&lt;br /&gt;    UIKeyboardCenterEndUserInfoKey = "NSPoint: {160, 372}";&lt;br /&gt;    UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 264}, {320, 216}}";&lt;br /&gt;    UIKeyboardFrameChangedByUserInteraction = 0;&lt;br /&gt;    UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 264}, {320, 216}}";&lt;br /&gt;}&lt;br /&gt;2011-10-19 10:35:15.513 SampleApp[5675:707] -[SampleViewController onUIKeyboardDidShowNotification:]&lt;br /&gt;2011-10-19 10:35:15.514 SampleApp[5675:707]   * userInfo = {&lt;br /&gt;    UIKeyboardAnimationCurveUserInfoKey = 0;&lt;br /&gt;    UIKeyboardAnimationDurationUserInfoKey = "0.35";&lt;br /&gt;    UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {320, 216}}";&lt;br /&gt;    UIKeyboardCenterBeginUserInfoKey = "NSPoint: {160, 372}";&lt;br /&gt;    UIKeyboardCenterEndUserInfoKey = "NSPoint: {160, 372}";&lt;br /&gt;    UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 264}, {320, 216}}";&lt;br /&gt;    UIKeyboardFrameChangedByUserInteraction = 0;&lt;br /&gt;    UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 264}, {320, 216}}";&lt;br /&gt;}&lt;br /&gt;2011-10-19 10:35:16.162 SampleApp[5675:707] -[SampleViewController viewDidAppear:]&lt;br /&gt;// キーボード引っ込める&lt;br /&gt;2011-10-19 10:35:44.246 SampleApp[5675:707] -[SampleViewController onUIKeyboardWillHideNotification:]&lt;br /&gt;2011-10-19 10:35:44.247 SampleApp[5675:707]   * userInfo = {&lt;br /&gt;    UIKeyboardAnimationCurveUserInfoKey = 0;&lt;br /&gt;    UIKeyboardAnimationDurationUserInfoKey = "0.25";&lt;br /&gt;    UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {320, 216}}";&lt;br /&gt;    UIKeyboardCenterBeginUserInfoKey = "NSPoint: {160, 372}";&lt;br /&gt;    UIKeyboardCenterEndUserInfoKey = "NSPoint: {160, 588}";&lt;br /&gt;    UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 264}, {320, 216}}";&lt;br /&gt;    UIKeyboardFrameChangedByUserInteraction = 0;&lt;br /&gt;    UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 480}, {320, 216}}";&lt;br /&gt;}&lt;br /&gt;2011-10-19 10:35:44.509 SampleApp[5675:707] -[SampleViewController onUIKeyboardDidHideNotification:]&lt;br /&gt;2011-10-19 10:35:44.511 SampleApp[5675:707]   * userInfo = {&lt;br /&gt;    UIKeyboardAnimationCurveUserInfoKey = 0;&lt;br /&gt;    UIKeyboardAnimationDurationUserInfoKey = "0.25";&lt;br /&gt;    UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {320, 216}}";&lt;br /&gt;    UIKeyboardCenterBeginUserInfoKey = "NSPoint: {160, 372}";&lt;br /&gt;    UIKeyboardCenterEndUserInfoKey = "NSPoint: {160, 588}";&lt;br /&gt;    UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 264}, {320, 216}}";&lt;br /&gt;    UIKeyboardFrameChangedByUserInteraction = 0;&lt;br /&gt;    UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 480}, {320, 216}}";&lt;br /&gt;}&lt;br /&gt;// キーボード出す&lt;br /&gt;2011-10-19 10:35:55.135 SampleApp[5675:707] -[SampleViewController onUIKeyboardWillShowNotification:]&lt;br /&gt;2011-10-19 10:35:55.136 SampleApp[5675:707]   * userInfo = {&lt;br /&gt;    UIKeyboardAnimationCurveUserInfoKey = 0;&lt;br /&gt;    UIKeyboardAnimationDurationUserInfoKey = "0.25";&lt;br /&gt;    UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {320, 216}}";&lt;br /&gt;    UIKeyboardCenterBeginUserInfoKey = "NSPoint: {160, 588}";&lt;br /&gt;    UIKeyboardCenterEndUserInfoKey = "NSPoint: {160, 372}";&lt;br /&gt;    UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 480}, {320, 216}}";&lt;br /&gt;    UIKeyboardFrameChangedByUserInteraction = 0;&lt;br /&gt;    UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 264}, {320, 216}}";&lt;br /&gt;}&lt;br /&gt;2011-10-19 10:35:55.397 SampleApp[5675:707] -[SampleViewController onUIKeyboardDidShowNotification:]&lt;br /&gt;2011-10-19 10:35:55.398 SampleApp[5675:707]   * userInfo = {&lt;br /&gt;    UIKeyboardAnimationCurveUserInfoKey = 0;&lt;br /&gt;    UIKeyboardAnimationDurationUserInfoKey = "0.25";&lt;br /&gt;    UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {320, 216}}";&lt;br /&gt;    UIKeyboardCenterBeginUserInfoKey = "NSPoint: {160, 588}";&lt;br /&gt;    UIKeyboardCenterEndUserInfoKey = "NSPoint: {160, 372}";&lt;br /&gt;    UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 480}, {320, 216}}";&lt;br /&gt;    UIKeyboardFrameChangedByUserInteraction = 0;&lt;br /&gt;    UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 264}, {320, 216}}";&lt;br /&gt;}&lt;br /&gt;// 日本語キーボードに変更&lt;br /&gt;2011-10-19 10:35:58.167 SampleApp[5675:707] -[SampleViewController onUIKeyboardWillShowNotification:]&lt;br /&gt;2011-10-19 10:35:58.168 SampleApp[5675:707]   * userInfo = {&lt;br /&gt;    UIKeyboardAnimationCurveUserInfoKey = 0;&lt;br /&gt;    UIKeyboardAnimationDurationUserInfoKey = 0;&lt;br /&gt;    UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {320, 252}}";&lt;br /&gt;    UIKeyboardCenterBeginUserInfoKey = "NSPoint: {160, 390}";&lt;br /&gt;    UIKeyboardCenterEndUserInfoKey = "NSPoint: {160, 354}";&lt;br /&gt;    UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 264}, {320, 216}}";&lt;br /&gt;    UIKeyboardFrameChangedByUserInteraction = 0;&lt;br /&gt;    UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 228}, {320, 252}}";&lt;br /&gt;}&lt;br /&gt;2011-10-19 10:35:58.170 SampleApp[5675:707] -[SampleViewController onUIKeyboardDidShowNotification:]&lt;br /&gt;2011-10-19 10:35:58.171 SampleApp[5675:707]   * userInfo = {&lt;br /&gt;    UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {320, 252}}";&lt;br /&gt;    UIKeyboardCenterBeginUserInfoKey = "NSPoint: {160, 390}";&lt;br /&gt;    UIKeyboardCenterEndUserInfoKey = "NSPoint: {160, 354}";&lt;br /&gt;    UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 264}, {320, 216}}";&lt;br /&gt;    UIKeyboardFrameChangedByUserInteraction = 0;&lt;br /&gt;    UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 228}, {320, 252}}";&lt;br /&gt;}&lt;br /&gt;// 英語キーボードに変更&lt;br /&gt;2011-10-19 10:36:00.483 SampleApp[5675:707] -[SampleViewController onUIKeyboardWillShowNotification:]&lt;br /&gt;2011-10-19 10:36:00.484 SampleApp[5675:707]   * userInfo = {&lt;br /&gt;    UIKeyboardAnimationCurveUserInfoKey = 0;&lt;br /&gt;    UIKeyboardAnimationDurationUserInfoKey = 0;&lt;br /&gt;    UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {320, 216}}";&lt;br /&gt;    UIKeyboardCenterBeginUserInfoKey = "NSPoint: {160, 336}";&lt;br /&gt;    UIKeyboardCenterEndUserInfoKey = "NSPoint: {160, 372}";&lt;br /&gt;    UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 228}, {320, 252}}";&lt;br /&gt;    UIKeyboardFrameChangedByUserInteraction = 0;&lt;br /&gt;    UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 264}, {320, 216}}";&lt;br /&gt;}&lt;br /&gt;2011-10-19 10:36:00.485 SampleApp[5675:707] -[SampleViewController onUIKeyboardDidShowNotification:]&lt;br /&gt;2011-10-19 10:36:00.486 SampleApp[5675:707]   * userInfo = {&lt;br /&gt;    UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {320, 216}}";&lt;br /&gt;    UIKeyboardCenterBeginUserInfoKey = "NSPoint: {160, 336}";&lt;br /&gt;    UIKeyboardCenterEndUserInfoKey = "NSPoint: {160, 372}";&lt;br /&gt;    UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 228}, {320, 252}}";&lt;br /&gt;    UIKeyboardFrameChangedByUserInteraction = 0;&lt;br /&gt;    UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 264}, {320, 216}}";&lt;br /&gt;}&lt;br /&gt;// 画面を抜ける、キーボードが隠れる通知より先にviewWillDissappearされるので通知が来ない&lt;br /&gt;2011-10-19 10:36:03.570 SampleApp[5675:707] -[SampleViewController viewWillDisappear:]&lt;br /&gt;2011-10-19 10:36:03.986 SampleApp[5675:707] -[SampleViewController viewDidDisappear:]&lt;/pre&gt;iOS 3.1.3, iPhone 3G&lt;pre&gt;2011-10-19 10:43:46.548 SampleApp[352:207] -[SampleViewController viewWillAppear:]&lt;br /&gt;// 前の画面の英字キーボードが一旦引っ込んで出てきているのだが、iOS 3.1.3では引っ込む側の挙動が見られない。出てくるだけになっているようだ。&lt;br /&gt;// さらにDidShowの通知がキーボードがviewDidAppearの呼び出しのあとに行われるようになっている。&lt;br /&gt;// どうやらキーボードがどこに属しているのかが違うみたいだな。&lt;br /&gt;2011-10-19 10:43:47.202 SampleApp[352:207] -[SampleViewController onUIKeyboardWillShowNotification:]&lt;br /&gt;2011-10-19 10:43:47.210 SampleApp[352:207]   * userInfo = {&lt;br /&gt;    UIKeyboardAnimationCurveUserInfoKey = 0;&lt;br /&gt;    UIKeyboardAnimationDurationUserInfoKey = 0.35;&lt;br /&gt;    UIKeyboardBoundsUserInfoKey = NSRect: {{0, 0}, {320, 216}};&lt;br /&gt;    UIKeyboardCenterBeginUserInfoKey = NSPoint: {480, 372};&lt;br /&gt;    UIKeyboardCenterEndUserInfoKey = NSPoint: {160, 372};&lt;br /&gt;}&lt;br /&gt;2011-10-19 10:43:48.253 SampleApp[352:207] -[SampleViewController viewDidAppear:]&lt;br /&gt;2011-10-19 10:43:48.315 SampleApp[352:207] -[SampleViewController onUIKeyboardDidShowNotification:]&lt;br /&gt;2011-10-19 10:43:48.336 SampleApp[352:207]   * userInfo = {&lt;br /&gt;    UIKeyboardBoundsUserInfoKey = NSRect: {{0, 0}, {320, 216}};&lt;br /&gt;    UIKeyboardCenterBeginUserInfoKey = NSPoint: {160, 588};&lt;br /&gt;    UIKeyboardCenterEndUserInfoKey = NSPoint: {160, 372};&lt;br /&gt;}&lt;br /&gt;// キーボード隠す&lt;br /&gt;2011-10-19 10:43:52.854 SampleApp[352:207] -[SampleViewController onUIKeyboardWillHideNotification:]&lt;br /&gt;2011-10-19 10:43:52.862 SampleApp[352:207]   * userInfo = {&lt;br /&gt;    UIKeyboardAnimationCurveUserInfoKey = 0;&lt;br /&gt;    UIKeyboardAnimationDurationUserInfoKey = 0.300000011920929;&lt;br /&gt;    UIKeyboardBoundsUserInfoKey = NSRect: {{0, 0}, {320, 216}};&lt;br /&gt;    UIKeyboardCenterBeginUserInfoKey = NSPoint: {160, 372};&lt;br /&gt;    UIKeyboardCenterEndUserInfoKey = NSPoint: {160, 588};&lt;br /&gt;}&lt;br /&gt;2011-10-19 10:43:53.183 SampleApp[352:207] -[SampleViewController onUIKeyboardDidHideNotification:]&lt;br /&gt;2011-10-19 10:43:53.188 SampleApp[352:207]   * userInfo = {&lt;br /&gt;    UIKeyboardBoundsUserInfoKey = NSRect: {{0, 0}, {320, 216}};&lt;br /&gt;    UIKeyboardCenterBeginUserInfoKey = NSPoint: {160, 372};&lt;br /&gt;    UIKeyboardCenterEndUserInfoKey = NSPoint: {160, 588};&lt;br /&gt;}&lt;br /&gt;// キーボード出す&lt;br /&gt;2011-10-19 10:43:54.621 SampleApp[352:207] -[SampleViewController onUIKeyboardWillShowNotification:]&lt;br /&gt;2011-10-19 10:43:54.629 SampleApp[352:207]   * userInfo = {&lt;br /&gt;    UIKeyboardAnimationCurveUserInfoKey = 0;&lt;br /&gt;    UIKeyboardAnimationDurationUserInfoKey = 0.300000011920929;&lt;br /&gt;    UIKeyboardBoundsUserInfoKey = NSRect: {{0, 0}, {320, 216}};&lt;br /&gt;    UIKeyboardCenterBeginUserInfoKey = NSPoint: {160, 588};&lt;br /&gt;    UIKeyboardCenterEndUserInfoKey = NSPoint: {160, 372};&lt;br /&gt;}&lt;br /&gt;2011-10-19 10:43:54.972 SampleApp[352:207] -[SampleViewController onUIKeyboardDidShowNotification:]&lt;br /&gt;2011-10-19 10:43:54.977 SampleApp[352:207]   * userInfo = {&lt;br /&gt;    UIKeyboardBoundsUserInfoKey = NSRect: {{0, 0}, {320, 216}};&lt;br /&gt;    UIKeyboardCenterBeginUserInfoKey = NSPoint: {160, 588};&lt;br /&gt;    UIKeyboardCenterEndUserInfoKey = NSPoint: {160, 372};&lt;br /&gt;}&lt;br /&gt;// キーボードの種類をここで英語→日本語、日本語→英語に変えているのだが、通知が来ない&lt;br /&gt;// だがiOS 3ではキーボードの種類によって高さが違うということが（基本）ないので気にしなくて良い&lt;br /&gt;[Switching to process 11779 thread 0x2e03]&lt;br /&gt;warning: No copy of &lt;no file name&gt; found locally, reading from memory on remote device.  This may slow down the debug session.&lt;br /&gt;// 画面抜ける、viewWillDisappearより先にKeyboardが隠れる通知が来る&lt;br /&gt;2011-10-19 10:44:07.442 SampleApp[352:207] -[SampleViewController onUIKeyboardWillHideNotification:]&lt;br /&gt;2011-10-19 10:44:07.454 SampleApp[352:207]   * userInfo = {&lt;br /&gt;    UIKeyboardAnimationCurveUserInfoKey = 0;&lt;br /&gt;    UIKeyboardAnimationDurationUserInfoKey = 0.35;&lt;br /&gt;    UIKeyboardBoundsUserInfoKey = NSRect: {{0, 0}, {320, 216}};&lt;br /&gt;    UIKeyboardCenterBeginUserInfoKey = NSPoint: {160, 372};&lt;br /&gt;    UIKeyboardCenterEndUserInfoKey = NSPoint: {480, 372};&lt;br /&gt;}&lt;br /&gt;2011-10-19 10:44:07.472 SampleApp[352:207] -[SampleViewController viewWillDisappear:]&lt;br /&gt;2011-10-19 10:44:08.374 SampleApp[352:207] -[SampleViewController viewDidDisappear:]&lt;/pre&gt;問題なさそうですね。キーボードの種類が切り替わったタイミングにもUIKeyboardWillShowNotificationとUIKeyboardWillHideNotificationがきちんと呼ばれているようです。これならUIKeyboardWillChangeFrameNotificationを使う必要はあんまり無いように思えます。実際、UIKeyboardWillChangeFrameNotificationを使わないでUIKeyboardWillShowNotificationとUIKeyboardWillHideNotificationだけを使ったアプリをリリースしていますが、特に問題なさそうです。&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-8843637828535490127?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/8843637828535490127/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=8843637828535490127' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/8843637828535490127'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/8843637828535490127'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/11/ios-5-ios-3-4-5.html' title='iOS 5の日本語キーボードの高さに対応する (iOS 3, 4, 5全対応)'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-1084936777202553888</id><published>2011-10-10T16:16:00.003+09:00</published><updated>2011-10-10T16:17:00.610+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iOS 4.3.5'/><category scheme='http://www.blogger.com/atom/ns#' term='BlueTooth'/><category scheme='http://www.blogger.com/atom/ns#' term='iPhone'/><category scheme='http://www.blogger.com/atom/ns#' term='iPad'/><category scheme='http://www.blogger.com/atom/ns#' term='Private API'/><title type='text'>iOS で Private API を使って Bluetooth Keyboard の状態を取ったりしたいメモ</title><content type='html'>iOS で Private API を使って Bluetooth Keyboard の状態を取ったりしたいメモです。言うまでもありませんが以下の参考資料に使われているコードとかを使ったアプリが App Store の審査に通ることは絶対にありません。真似しないでね！&lt;br /&gt;あと以下のコードを使って実機で試したコードがまだないので、Jailbrake していない iOS 4.3.5 で動くかどうかすらわかりません。すみません＞＜&lt;br /&gt;&lt;br /&gt;GSEventを使ってKeyboardの修飾キーの状態を得る&lt;br /&gt;&lt;a href="https://gist.github.com/1242475"&gt;https://gist.github.com/1242475&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;iPhoneのイヤフォンマイクやBluetoothキーボードでシャッターを切れるようにするiRemoteShutter&lt;br /&gt;&lt;a href="http://hitoriblog.com/?p=1747"&gt;http://hitoriblog.com/?p=1747&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;iSSHのBluetoothキーボード対応を強化するiSSHPatcher&lt;br /&gt;&lt;a href="http://hitoriblog.com/?p=1798"&gt;http://hitoriblog.com/?p=1798&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;BluetoothキーボードからiPhone/iPadのタスクスイッチを可能にするAltTab&lt;br /&gt;&lt;a href="http://hitoriblog.com/?p=3958"&gt;http://hitoriblog.com/?p=3958&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;BluetoothManager&lt;br /&gt;&lt;a href="http://stackoverflow.com/questions/1743610/programmatically-turn-on-bluetooth-in-the-iphone-sdk"&gt;http://stackoverflow.com/questions/1743610/programmatically-turn-on-bluetooth-in-the-iphone-sdk&lt;/a&gt;&lt;br /&gt;BluetoothDeviceを使えばデバイスの電池残量とかも見られそう&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-1084936777202553888?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/1084936777202553888/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=1084936777202553888' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/1084936777202553888'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/1084936777202553888'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/10/ios-private-api-bluetooth-keyboard.html' title='iOS で Private API を使って Bluetooth Keyboard の状態を取ったりしたいメモ'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-5172354874706405399</id><published>2011-09-18T21:03:00.002+09:00</published><updated>2011-09-18T21:04:28.876+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Objective-C'/><category scheme='http://www.blogger.com/atom/ns#' term='Cocoa'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><title type='text'>iOS, Android, Windows Phoneのメモリ管理とかメッセージングの仕方を調べてみた</title><content type='html'>ぼちぼちTwitterにつぶやいていたらTogetterにまとめてくださった方がいらっしゃるので、せっかくなのでこちらでも紹介したいと思います。&lt;br /&gt;&lt;br /&gt;&lt;a href="http://togetter.com/li/189550"&gt;http://togetter.com/li/189550&lt;/a&gt; （githubみたいにembedできればいいのになーなんて＞＜）&lt;br /&gt;&lt;br /&gt;結構気合い入れて調べたのでおすすめです。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-5172354874706405399?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/5172354874706405399/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=5172354874706405399' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/5172354874706405399'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/5172354874706405399'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/09/ios-android-windows-phone.html' title='iOS, Android, Windows Phoneのメモリ管理とかメッセージングの仕方を調べてみた'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-351496698718316674</id><published>2011-09-12T09:55:00.000+09:00</published><updated>2011-09-12T10:00:42.772+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iOS 4.3.5'/><category scheme='http://www.blogger.com/atom/ns#' term='iPhone'/><category scheme='http://www.blogger.com/atom/ns#' term='iPad'/><category scheme='http://www.blogger.com/atom/ns#' term='Cocoa'/><category scheme='http://www.blogger.com/atom/ns#' term='UI'/><title type='text'>UIWebView の Private API を使って BASIC認証のあるページにアクセスする</title><content type='html'>元ネタはこちら: &lt;a href="http://d.hatena.ne.jp/KishikawaKatsumi/20090603/1243968707"&gt;http://d.hatena.ne.jp/KishikawaKatsumi/20090603/1243968707&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;仕事でどうしても以下の要件を満たすUIWebViewが必要になったので作りました。&lt;ul&gt;&lt;li&gt;開発環境にBASIC認証がかかっており、そこにUIWebViewでアクセスしたい。&lt;/li&gt;&lt;li&gt;アクセス先のHTMLにリンクが埋め込まれているため、URLをhttp://username:password@example.comのように変換することができない。webView:shouldStartLoadWithRequest:navigationType:で頑張ればいける気がしなくともないのですが結局断念しました。&lt;/li&gt;&lt;li&gt;諸事情によりNSURLConnectionが使えない（当然ASIもダメ。あくまでUIWebViewでアクセスする必要がある）。&lt;/li&gt;&lt;/ul&gt;普通につくるとどうにもうまくいかなかったので、結局UIWebViewをオーバーライドしてPrivate APIを叩く作戦を取ることにしました。&lt;br /&gt;&lt;br /&gt;というわけで出来上がったソースコードはこちら。MITライセンスです。&lt;br /&gt;&lt;a href="https://gist.github.com/1210372"&gt;https://gist.github.com/1210372&lt;/a&gt;&lt;br /&gt;iOS 4.3.5で動作確認しています。iOS 5でも多分動作します。 iOS 3以下はわかりません＞＜&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; color:#cc0000;"&gt;注意: このコードにはPrivate APIが多分に含まれています。このコードが含まれたアプリをApp Storeに提出しても十中八九審査に通りません。あくまで開発環境での検証用または自分のiPhoneに入れてニヤニヤするコードにのみお使いください。&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■しくみ&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;UIKitをclass-dumpしてたら使えそうなシグネチャを見つけたので、継承してオーバーライドしてゴニョゴニョしてたらできちゃった！って感じです。それにしてもWebKitはPrivate APIにしておくにはもったいない出来の良さですね。このAPIへのフルアクセスがあればAndroidのWebViewと同等かそれ以上に自由に使えるのですが。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-351496698718316674?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/351496698718316674/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=351496698718316674' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/351496698718316674'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/351496698718316674'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/09/uiwebview-private-api-basic.html' title='UIWebView の Private API を使って BASIC認証のあるページにアクセスする'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-5802520584387849151</id><published>2011-08-22T22:48:00.021+09:00</published><updated>2011-09-09T00:02:28.712+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ライブラリ'/><category scheme='http://www.blogger.com/atom/ns#' term='iOS 4.3.5'/><category scheme='http://www.blogger.com/atom/ns#' term='iPhone'/><category scheme='http://www.blogger.com/atom/ns#' term='iPad'/><category scheme='http://www.blogger.com/atom/ns#' term='Objective-C'/><category scheme='http://www.blogger.com/atom/ns#' term='セキュリティ'/><category scheme='http://www.blogger.com/atom/ns#' term='Cocoa'/><title type='text'>UDIDが使えなくなりそうなので、UIIDを使えるようにしました</title><content type='html'>つい先日&lt;a href="http://techcrunch.com/2011/08/19/apple-ios-5-phasing-out-udid/"&gt;TechCrunchがiOS5よりUDIDの使用が非推奨になると報道し&lt;/a&gt;、巷はiOSでのUDIDの使用についての話題で俄然盛り上がっています。セキュリティ的によろしくないから良い変更だという声もあれば、すでに認証用として使っていてシステム改修が必要という悲観の声もあります。しかし私はどちらかというとUDIDをバリバリ使っちゃってる方陣営の人なので、セキュリティの問題については知っていても、やはりUDID相当の物が無いと不便だなぁと思ってしまうのです。そこでプログラマらしくコードで解決することにしました。 &lt;br /&gt;&lt;br /&gt;UDIDにはセキュリティの懸念があるし、もう使えなくなる。だったらもっといいIDを超簡単に生成して使えるようにすればいいじゃない。ということでUnique Installation Identifier (インストール毎ID、UIID) を生成するライブラリを早速書いてみました。 &lt;br /&gt;ソースコードはこちら。MITライセンスです。 &lt;br /&gt;&lt;a href="https://github.com/akisute/UIApplication-UIID"&gt;https://github.com/akisute/UIApplication-UIID&lt;/a&gt; &lt;br /&gt;&lt;a href="https://gist.github.com/1161447"&gt;昔のgistはこちら&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;使い方は超簡単で、&lt;ol&gt;&lt;li&gt;アプリが一度削除されたとしても同一のUIIDを返すようにしたいのであれば、&lt;code&gt;#define UIID_PERSISTENT=1&lt;/code&gt;して、Security.frameworkをプロジェクトに追加する&lt;/li&gt;&lt;li&gt;UIApplication+UIID.hをimport&lt;/li&gt;&lt;li&gt;&lt;code&gt;[[UIApplication sharedApplication] uniqueInstallationIdentifier]&lt;/code&gt;で取れます&lt;/li&gt;&lt;/ol&gt;はいこれだけです。 &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■そもそもどうしてUDIDを使うのか&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;たいていの場合は以下のような理由です。&lt;ul&gt;&lt;li&gt;ログイン機構なしに簡易にユーザーの識別をしたいときに、毎回同じ値を返し、かつユーザー事に異なる値が取得出来る何かが必要になるので、UDIDを使う&lt;/li&gt;&lt;li&gt;UDID値の取得がいつでもどこでも可能、さらに超簡単で外部ライブラリのインストールなど面倒なことが一切無い&lt;/li&gt;&lt;li&gt;&lt;a href="http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIDevice_Class/Reference/UIDevice.html#//apple_ref/occ/instp/UIDevice/uniqueIdentifier"&gt;しかもAppleのドキュメントにそう使えって書いてある。&lt;/a&gt;・・・補足すると使ってもいいよ、ぐらいのニュアンスで、使えという風に推奨はしてないみたいです＞＜ またUDIDのみをキーとしてユーザー情報を保存するな、とも書いてますね。&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■UDIDは何がまずいの&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;主にまずい理由はセキュリティです。&lt;a href="http://takagi-hiromitsu.jp/diary/20080710.html#p01"&gt;特にガラケーのかんたんログインの問題が参考になるのですが、&lt;/a&gt;iOSの場合は以下のようなセキュリティ問題が発生します。&lt;ul&gt;&lt;li&gt;相手のUDIDがわかってしまえば、簡単になりすましが可能&lt;/li&gt;&lt;li&gt;UDIDの値を返すメソッドの実装を差し替えて、任意の値を返すように出来る。JailBreakしているユーザーであれば誰でも簡単に実行可能、そのためのアプリもCydiaで検索すれば転がっている&lt;/li&gt;&lt;li&gt;UDID自体、様々な方法で取得可能。アプリをインストールさせてそこ経由で集めてみたりはもちろん（その際値を取得することに対する警告すら出ない）、iTunesからでも値を確認できる&lt;/li&gt;&lt;li&gt;上記三つの理由のため、その気になればたやすく任意のユーザーになりすませる&lt;/li&gt;&lt;li&gt;さらに恐ろしいことにUDIDは端末事に一意になるため、一度値が特定されてしまうと端末を買い換えない限りずっとなりすまされてしまう、リセットできない&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■UIIDだとどうなる&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;Unique Installation Identifier, UIIDはUDIDと異なり「アプリのインストール基盤毎」に一意な値を返すような実装になっています。簡単にまとめると、あるアプリAが、デバイス1, 2, 3にインストールされた場合、UIIDは1, 2, 3の全てで異なる値になります。ここまではUDIDと同じですが、UDIDと違うのはデバイス1に別々のアプリA, B, Cがインストールされた場合、それぞれ異なる値になります。中身は単にCFUUIDというiOSに元からある良くできたID生成ルーチンなんですが、これにより以下のようなメリットが得られます。&lt;ul&gt;&lt;li&gt;外部からIDの値を取得するのが困難。推測も十分に長い上に独立な値なため困難、取得も（UIID_PERSISTENT=1でビルドすればKeychainを使うので）困難です。&lt;/li&gt;&lt;li&gt;万が一何かの間違いで流出したとしても、アプリごとに異なる値になるため他のアプリのセキュリティが犯されたりはしない。また同様の理由で他の悪意のあるアプリからUIIDを取得して攻撃することもできない。&lt;/li&gt;&lt;li&gt;プログラム的にUIIDをリセット可能。UUID_PERSISTENT=0であればアプリを消せばユーザーが任意にリセット可能。&lt;/li&gt;&lt;li&gt;Keychainを使ったメリットとして、ユーザーがデバイスを乗り換えてもiTunesのバックアップに値が保持されるため、それから復元を行った場合UIIDの値が引き継がれる。&lt;/li&gt;&lt;li&gt;通常のアプリであればUDIDを使っていたケースのほとんどはこのUIIDでそのまま代用可能、あとは過去のUDIDとUIIDのヒモ付だけサーバー側でやってしまえば完全に乗り換えられる&lt;/li&gt;&lt;li&gt;それでもどうしてもデバイスごとに一意な値が欲しいなら&lt;a href="https://github.com/gekitz/UIDevice-with-UniqueIdentifier-for-iOS-5/blob/master/Classes/UIDevice+IdentifierAddition.m"&gt;https://github.com/gekitz/UIDevice-with-UniqueIdentifier-for-iOS-5/blob/master/Classes/UIDevice+IdentifierAddition.m&lt;/a&gt;など使えばよいのかなと。ただしこの実装はMACアドレスの値を使っているため、MACアドレスの値がわかってしまえばIDをたやすく生成可能で、UDIDの持つセキュリティ上の問題は残ります。&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■使用上の注意&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;UDIDよりは問題が少ないですが、それでもこのUIIDだけで認証を行うような作りのアプリには間違ってもしないように！以下のような問題があります。&lt;ul&gt;&lt;li&gt;そもそもこの値は完全にユーザーと一意にヒモ付いた値ではありません。UIIDはあくまでアプリのインストール単位とヒモ付いているだけです。複数のデバイスを一人のユーザーが所有していたりすると完全にアウトですし、インストールされた端末が譲与された場合も対応できません。&lt;/li&gt;&lt;li&gt;プログラム的にUIIDはリセット可能なので最悪の場合でもずっとなりすまされるのは回避できるのですが、その際にヒモ付けられていたユーザー固有の情報が消えてしまいます。ログインIDとパスワードで認証をしているのであれば、ログインIDはそのままにしてパスワードだけをリセットすることで、なりすましの問題を解決しつつ、ユーザーの一意性は保ったままにできるため、万が一の際はログインIDとパスワードを使っている方が圧倒的に利便性が高まります。&lt;/li&gt;&lt;li&gt;以上の理由により、UIIDはあくまで簡易的・一時的にユーザー認証をする時に使用し（たとえばユーザーが購入したアプリ内課金の商品をアプリが消されるまでの間だけ履歴として持っておいたり、ゲームのランキング等で匿名だけれど点数ランキングに参加できるようにしたり）、正式で完全なサービスはログインIDとパスワードによって提供するべきです。そうすることで一人のユーザーが複数のデバイスでサービスを使えるようになります。さらにはAndroidとも連携できたりしますしお得です。&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■っていうか&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;&lt;a href="http://takagi-hiromitsu.jp/diary/20100619.html"&gt;全部高木先生が一年前に言っている通りになっちゃってるじゃないすか！&lt;/a&gt;っていうか私が作った物もこの高木先生がおっしゃってる「アプリ専用の（セキュアな）独自IDを生成してそれを保存して使う」というものの実装にすぎません。しかしまったく、せっかく警告してもらっても、人間実際に問題に直面しなければなかなか手をつけないものですね＞＜ &lt;br /&gt;&lt;br /&gt;しかし、しかしですね、あえてここで一言、エンジニアとして申させていただきたい。 &lt;br /&gt;&lt;br /&gt;私、エンジニアが欲しいのはセキュリティ上正しい実装の方法だとか、概念だとか、ましてやどこそこのログイン方法はいけてないから直せや、などという文章でもないのです。我々が欲しいのは、「すでに実装されている、セキュリティ上正しくて、猿でも理解できて、1分で組み込めて、どのような環境でも動き、ユーザーが会員登録なんて面倒極まりないことをしなくても済むユーザー認証の手段」なんです。要するに、&lt;pre&gt;// 何か良くわからんけどこのトークンをHTTPS経由でPOSTして認証しておけば超スーパー確実かつセキュアで猿でも実装できてハッピーになる&lt;br /&gt;[[NSAuthentication sharedUser] authenticationToken]&lt;/pre&gt;↑コレが今すぐ欲しいんですよ、我々エンジニアというのは。そうすれば誰だってUDIDを使って認証するみたいな面倒くさいことするわけ無いじゃないですか。頼まれたってやりませんよ。 &lt;br /&gt;&lt;br /&gt;私はユーザー認証をしたいだけなんです、それも可能な限り楽に。口で何と批判しようが、正しい方法を教えようが、世の中は決して変わらないと思います。みんな楽をしたいから。なのでAppleには是非UDIDを廃止するこの機会にぜひ上記のような何かをUIKitなりFoundationなりに組み込んで欲しいですね。こういうところも、良いプラットフォーマーの責務の一部じゃないかなと。 &lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-5802520584387849151?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/5802520584387849151/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=5802520584387849151' title='8 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/5802520584387849151'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/5802520584387849151'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/08/udiduiid.html' title='UDIDが使えなくなりそうなので、UIIDを使えるようにしました'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-3092379718072040269</id><published>2011-08-12T21:41:00.003+09:00</published><updated>2011-08-12T21:43:52.084+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iOS 4.3.5'/><category scheme='http://www.blogger.com/atom/ns#' term='iPhone'/><category scheme='http://www.blogger.com/atom/ns#' term='iPad'/><category scheme='http://www.blogger.com/atom/ns#' term='Cocoa'/><category scheme='http://www.blogger.com/atom/ns#' term='ImageIO'/><title type='text'>iOS で ImageIO を使ってアニメーションGIFファイルを生成してみる</title><content type='html'>参考にしたのはこちら。&lt;br /&gt;&lt;a href="http://pojos-devlog.blogspot.com/2005/08/saving-animated-gif-using-coregraphics.html"&gt;http://pojos-devlog.blogspot.com/2005/08/saving-animated-gif-using-coregraphics.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;iOS 4以降でよければImageIOフレームワークが使えるためむちゃくちゃ簡単です。任意のUIImage / CGImageRefから好きなようにアニメーションGIFを生成できます。&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1141953.js?file=gistfile1.m"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;iOS 3以前の場合は・・・頑張れとしか・・・&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-3092379718072040269?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/3092379718072040269/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=3092379718072040269' title='1 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/3092379718072040269'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/3092379718072040269'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/08/ios-imageio-gif.html' title='iOS で ImageIO を使ってアニメーションGIFファイルを生成してみる'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-6515182639981271960</id><published>2011-08-12T19:59:00.003+09:00</published><updated>2011-08-12T20:03:43.111+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iOS 4.3.5'/><category scheme='http://www.blogger.com/atom/ns#' term='iPhone'/><category scheme='http://www.blogger.com/atom/ns#' term='iPad'/><category scheme='http://www.blogger.com/atom/ns#' term='Cocoa'/><category scheme='http://www.blogger.com/atom/ns#' term='Core Data'/><title type='text'>メモ: CoreDataで更新処理をするときは、lockをわすれずに</title><content type='html'>単なるメモ書きです＞＜&lt;br /&gt;&lt;br /&gt;&lt;a href="http://twitter.com/#!/akisutesama/status/83521489382555650"&gt;http://twitter.com/#!/akisutesama/status/83521489382555650&lt;/a&gt;&lt;br /&gt;&lt;a href="http://twitter.com/#!/akisutesama/status/83521729380626433"&gt;http://twitter.com/#!/akisutesama/status/83521729380626433&lt;/a&gt;&lt;blockquote&gt;ある一つのCore Dataのモデルを非同期的に複数箇所から更新するときは、たとえどんなに軽微な、プロパティ一つだけの、他からは触られない様な変更ですら、きちんとlockを取らないと危険ということがわかった。API実行クラスだけでは不十分であった。非同期であればロック必須。&lt;/blockquote&gt;&lt;blockquote&gt;変更を行うコードブロックを渡して、内部で安全にロックして実行、必要に応じてロールバックや失敗通知も行える様にする仕組みを作ろうと思った。&lt;/blockquote&gt;CoreDataのモデルオブジェクトの更新はただのsetterプロパティの使用だけで発生してしまうのでついつい忘れがちになるのですが、これが原因で実際にクラッシュしたアプリもあるので油断禁物。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-6515182639981271960?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/6515182639981271960/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=6515182639981271960' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/6515182639981271960'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/6515182639981271960'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/08/coredatalock.html' title='メモ: CoreDataで更新処理をするときは、lockをわすれずに'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-3125393043608160389</id><published>2011-08-12T08:29:00.006+09:00</published><updated>2011-08-12T21:46:52.670+09:00</updated><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='iOS 4.0'/><category scheme='http://www.blogger.com/atom/ns#' term='Cocoa'/><title type='text'>UIPanGestureRecognizerはiOS4.0ではtranslationプロパティを正しく返さない</title><content type='html'>UIPanGestureRecognizerのtranslationプロパティは、iOS 4.0でかつUIScrollViewの配下になっているviewに対して取り付けた場合、常にCGPointZeroを返してしまうようです。iOS 4.1のシミュレータで確認したら直ってましたので、iOS 4.0限定だと思われます。というわけでvelocityプロパティをかわりに使っておくことをお進めします。&lt;br /&gt;&lt;br /&gt;検証結果はこちら&lt;br /&gt;&lt;script src="https://gist.github.com/1138725.js?file=gistfile1.m"&gt;&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-3125393043608160389?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/3125393043608160389/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=3125393043608160389' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/3125393043608160389'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/3125393043608160389'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/08/uipangesturerecognizerios40translation.html' title='UIPanGestureRecognizerはiOS4.0ではtranslationプロパティを正しく返さない'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-8671222732565266222</id><published>2011-08-12T08:28:00.002+09:00</published><updated>2011-08-12T08:32:32.691+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iOS 4.3.5'/><category scheme='http://www.blogger.com/atom/ns#' term='iPhone'/><category scheme='http://www.blogger.com/atom/ns#' term='iPad'/><category scheme='http://www.blogger.com/atom/ns#' term='Cocoa'/><title type='text'>[NSObject load] と [NSObject initialize] の違い</title><content type='html'>クラスがObjective-Cのランタイムにロードされ利用可能になったタイミングで、そのクラス全体の初期化を行いたいということはよくあると思います。Objective-CではNSObjectクラスの以下のメソッドを用いてクラス全体の初期化を行うことができます。&lt;ul&gt;&lt;li&gt; + load&lt;/li&gt;&lt;li&gt; + initialize&lt;/li&gt;&lt;/ul&gt;この２つですが、結構挙動が異なります。詳細については以下のとおり。&lt;br /&gt;&lt;a href="http://cocoawithlove.com/2008/03/cocoa-application-startup.html"&gt;http://cocoawithlove.com/2008/03/cocoa-application-startup.html&lt;/a&gt;&lt;ul&gt;&lt;li&gt;loadメソッドはクラスがロードされて利用可能になったら即座に呼び出される。&lt;ul&gt;&lt;li&gt;このとき、自分以外の他のクラスはまだロードされていない可能性があるので、自分以外のクラスを利用するような初期化はできない。&lt;/li&gt;&lt;li&gt;main関数の内部のNSAutoReleasePoolが用意されるよりも先に呼び出されるので、autoreleaseを使うような初期化を行う場合には自分でNSAutoReleasePoolを生成して管理する必要がある&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;initializeメソッドはそのクラスに実際のアクセスが最初に発生したタイミングで呼び出される。&lt;ul&gt;&lt;li&gt;要するに一度も使われないクラスでは呼び出されない。&lt;/li&gt;&lt;li&gt;自分以外のクラスもロードが完了しているので、自由に他のクラスを利用できる。&lt;/li&gt;&lt;li&gt;autoreleaseについても特に気にしなくて良い。&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;基本はinitializeメソッドを使うほうがより安全で確実なうえに、使われないなら初期化されないので経済的でいい感じです。こちらを使うことをお勧めします。&lt;br /&gt;&lt;br /&gt;またloadメソッドについては、iOS実機で自家製frameworkを使っているを使っているとき、framework内部にビルドされているクラスのloadメソッドが呼び出されないという問題があります（静的ライブラリ.aについては未検証）iOSシミュレータおよびMacではきちんとframeworkに含まれているクラスについてもloadメソッドが呼び出されるのですが・・・ともかく地雷が大きいので避けたほうが懸命です。&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-8671222732565266222?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/8671222732565266222/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=8671222732565266222' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/8671222732565266222'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/8671222732565266222'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/08/nsobject-load-nsobject-initialize.html' title='[NSObject load] と [NSObject initialize] の違い'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-4173263091069888620</id><published>2011-08-12T08:02:00.003+09:00</published><updated>2011-08-12T08:09:20.083+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iOS 4.3.5'/><category scheme='http://www.blogger.com/atom/ns#' term='iPhone'/><category scheme='http://www.blogger.com/atom/ns#' term='iPad'/><category scheme='http://www.blogger.com/atom/ns#' term='Cocoa'/><title type='text'>[UIView willMoveToSuperview:] が便利です</title><content type='html'>UIKitやFoundationには、iOS 2.0のころから存在するのに、意外と知られていない便利なメソッドやプロパティがたくさんあります。今回はUIViewのメソッドをご紹介します。&lt;br /&gt;&lt;br /&gt;UIViewはUIViewControllerと違ってライフサイクルが単純で、どのタイミングで自分自身が画面上に追加されたのか、どのタイミングで自分自身が画面から外されたのか、などを把握しづらいとお嘆きの方がいらっしゃると思います。事実その用途のためだけにUIViewControllerを使ってプログラミングをしている人も見かけます。そこで以下のメソッドをご紹介です。&lt;ul&gt;&lt;li&gt;willMoveToSuperview:&lt;ul&gt;&lt;li&gt;自分自身が新しいSuperview以下に移動しようとしたとき（新しいSuperviewに対してaddSubview:されようとしたとき）に呼び出されます。&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;didMoveToSuperview&lt;ul&gt;&lt;li&gt;自分自身が新しいSuperview以下に移動したとき（新しいSuperviewにaddSubview:されたとき）に呼び出されます。&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;willMoveToWindow:&lt;ul&gt;&lt;li&gt;自分自身が新しいWindow以下に移動しようとしたとき（新しいWindowに対してaddSubview:されようとしたとき）に呼び出されます。&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;didMoveToWindow&lt;ul&gt;&lt;li&gt;自分自身が新しいWindow以下に移動したとき（新しいWindowに対してaddSubview:されたとき）に呼び出されます。&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;didAddSubview:&lt;ul&gt;&lt;li&gt;自分自身に他のviewがsubviewとして追加されたときに呼び出されます。&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;willRemoveSubview:&lt;ul&gt;&lt;li&gt;自分自身のsubviewsから他のviewが取り除かれようとしているときに呼び出されます。&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;これらのメソッドをUIViewのサブクラスでオーバーライドすることにより、かなりの自由度でviewの動きをコントロールすることができます。&lt;br /&gt;たとえば自作のUIViewで、画面にviewが追加されたタイミングで何かしたい・・・というときなどは以下のようにできます:&lt;pre class="prettyprint linenums"&gt;- (void)willMoveToSuperview:(UIView *)newSuperview&lt;br /&gt;{&lt;br /&gt;    NSLog(@"  * superview = %@", newSuperview);&lt;br /&gt;    NSLog(@"  * superview's window = %@", newSuperview.window);&lt;br /&gt;    // UIViewControllerでいうところの loadView 兼 viewDidLoad 兼 viewWillAppear 兼 viewWillDisappearみたいなタイミング&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;- (void)didMoveToSuperview&lt;br /&gt;{&lt;br /&gt;    // UIViewControllerでいうところの viewDidAppear 兼 viewDidDisappear みたいなタイミング&lt;br /&gt;    // ここで、もしsuperviewがあり（画面に表示される可能性があり）、まだ自分自身のデータが初期化されていない場合には&lt;br /&gt;    // reloadDataして初期表示データを読み込む&lt;br /&gt;    // superviewがない場合には画面から外されたのですべてのビューまわりをリセットして、次の表示に備えるようにしておく&lt;br /&gt;    if (self.superview) {&lt;br /&gt;        if (!self.someData) {&lt;br /&gt;            [self reloadData];&lt;br /&gt;        }&lt;br /&gt;    } else {&lt;br /&gt;        self.someData = nil;&lt;br /&gt;        [self __resetOutlets];&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;- (void)willMoveToWindow:(UIWindow *)newWindow&lt;br /&gt;{&lt;br /&gt;    NSLog(@"  * window = %@", newWindow);&lt;br /&gt;    // いまいち使いづらいのでwillMoveToSuperviewとかを使うようにしてます&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;- (void)didMoveToWindow&lt;br /&gt;{&lt;br /&gt;    // いまいち使いづらいのでdidMoveToSuperviewを使うようにしてます&lt;br /&gt;}&lt;/pre&gt;これでUIViewの使い勝手もアップ！ですね。&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-4173263091069888620?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/4173263091069888620/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=4173263091069888620' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/4173263091069888620'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/4173263091069888620'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/08/uiview-willmovetosuperview.html' title='[UIView willMoveToSuperview:] が便利です'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-799318523892110028</id><published>2011-08-09T08:23:00.009+09:00</published><updated>2011-08-09T08:53:14.653+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iOS 4.3.5'/><category scheme='http://www.blogger.com/atom/ns#' term='iPhone'/><category scheme='http://www.blogger.com/atom/ns#' term='iPad'/><category scheme='http://www.blogger.com/atom/ns#' term='Cocoa'/><title type='text'>[UITableViewController scrollToRowAtIndexPath:atScrollPosition:animated:] の挙動まとめ</title><content type='html'>UITableViewController の scrollToRowAtIndexPath:atScrollPosition:animated: メソッドは、対象のテーブルビューのセクションにヘッダ・フッタが付いている場合挙動が変化する事がわかったので、ちょっと調査してまとめてみました。具体的には以下のような動きをするようです。&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;このメソッドは自分で呼び出すか、またはテーブルビューのセルの中に UITextField のようなフォーカスを取るコントロールを配置して、それが選択されたときに呼び出される&lt;/li&gt;&lt;li&gt;このメソッドで指定した indexPath の section に Header View or Header Text / Footer View or Footer Text が指定されているとき、このメソッドは選択された indexPath の row だけではなく、それらのヘッダやフッタも同時に表示される位置にスクロールしようとする&lt;/li&gt;&lt;li&gt;ということであんまり長い Section Header / Section Footer を作ると scrollToRowAtIndexPath:atScrollPosition:animated: の挙動がおかしくなる&lt;/li&gt;&lt;li&gt;Table View Header / Table View Footer については全然無関係なので長くしても大丈夫&lt;/li&gt;&lt;/ul&gt;画像にすると以下のような感じになります。&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;初期状態&lt;/span&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-nsoX1Acu4Bs/TkBwQh_a0oI/AAAAAAAACqQ/9M9k73ytLSU/s1600/default.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 213px; height: 400px;" src="http://3.bp.blogspot.com/-nsoX1Acu4Bs/TkBwQh_a0oI/AAAAAAAACqQ/9M9k73ytLSU/s400/default.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5638630162772447874" /&gt;&lt;/a&gt;&lt;br /&gt;section３つ、row３つ、合計９行のtable viewを作って、それぞれにsection header / section footerを追加しました。このテーブルビューを使って実験を行います。&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;UITableViewScrollPositionTopを指定してスクロール&lt;/span&gt;&lt;br /&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;section0, row0&lt;/td&gt;&lt;td&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-QNOKUISF79k/TkBwQkflw3I/AAAAAAAACqY/k9xLSZlDVrs/s1600/top1.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 213px; height: 400px;" src="http://2.bp.blogspot.com/-QNOKUISF79k/TkBwQkflw3I/AAAAAAAACqY/k9xLSZlDVrs/s400/top1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5638630163444253554" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;section0, row1&lt;/td&gt;&lt;td&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-m7HfoQ6qSO4/TkBwQw1UIhI/AAAAAAAACqg/BvnXio-D76A/s1600/top2.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 213px; height: 400px;" src="http://2.bp.blogspot.com/-m7HfoQ6qSO4/TkBwQw1UIhI/AAAAAAAACqg/BvnXio-D76A/s400/top2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5638630166756598290" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/td&gt;&lt;td&gt;section0, row2&lt;/td&gt;&lt;td&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-PNNz29j3QdU/TkBwQzEgByI/AAAAAAAACqo/OpC6QCakblI/s1600/top3.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 213px; height: 400px;" src="http://2.bp.blogspot.com/-PNNz29j3QdU/TkBwQzEgByI/AAAAAAAACqo/OpC6QCakblI/s400/top3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5638630167357163298" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;section1, row0&lt;/td&gt;&lt;td&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-i3EgFhqyT4Y/TkBwRNupvMI/AAAAAAAACqw/VTbpZC0ZRA0/s1600/top4.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 213px; height: 400px;" src="http://4.bp.blogspot.com/-i3EgFhqyT4Y/TkBwRNupvMI/AAAAAAAACqw/VTbpZC0ZRA0/s400/top4.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5638630174513282242" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;UITableViewScrollPositionTopを指定すると、sectionの一番上のrowが指定された場合のみ、そのsectionのsection headerの高さを考慮してスクロールするようになります。&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;UITableViewScrollPositionMiddleを指定してスクロール&lt;/span&gt;&lt;br /&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;section0, row0&lt;/td&gt;&lt;td&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-h-4L-dV3ESs/TkBy1blfbBI/AAAAAAAACq4/eHcGVgAM_U4/s1600/middle1.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 213px; height: 400px;" src="http://3.bp.blogspot.com/-h-4L-dV3ESs/TkBy1blfbBI/AAAAAAAACq4/eHcGVgAM_U4/s400/middle1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5638632995731500050" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;section0, row1&lt;/td&gt;&lt;td&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-t2eEG2GBmJc/TkBy1qK6SiI/AAAAAAAACrA/h7aH35Hochc/s1600/middle2.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 213px; height: 400px;" src="http://3.bp.blogspot.com/-t2eEG2GBmJc/TkBy1qK6SiI/AAAAAAAACrA/h7aH35Hochc/s400/middle2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5638632999646546466" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;section0, row2&lt;/td&gt;&lt;td&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-Ay2MDmWVdL4/TkBy1n0z8qI/AAAAAAAACrI/BU4SfNqkNgc/s1600/middle3.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 213px; height: 400px;" src="http://4.bp.blogspot.com/-Ay2MDmWVdL4/TkBy1n0z8qI/AAAAAAAACrI/BU4SfNqkNgc/s400/middle3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5638632999016985250" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;section1, row0&lt;/td&gt;&lt;td&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-Ju4AkU4cs5w/TkBzGgElUCI/AAAAAAAACrQ/wWE2w5GRTEk/s1600/middle4.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 213px; height: 400px;" src="http://2.bp.blogspot.com/-Ju4AkU4cs5w/TkBzGgElUCI/AAAAAAAACrQ/wWE2w5GRTEk/s400/middle4.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5638633288993427490" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;section1, row1&lt;/td&gt;&lt;td&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-WqdQhFR4CL8/TkBzH21ZcKI/AAAAAAAACrY/gUApkjFzRXk/s1600/middle5.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 213px; height: 400px;" src="http://3.bp.blogspot.com/-WqdQhFR4CL8/TkBzH21ZcKI/AAAAAAAACrY/gUApkjFzRXk/s400/middle5.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5638633312283619490" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;section1, row2&lt;/td&gt;&lt;td&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-u9U6UD4-zJ8/TkBzIyNctqI/AAAAAAAACrg/WXVjf_-Eqo8/s1600/middle6.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 213px; height: 400px;" src="http://2.bp.blogspot.com/-u9U6UD4-zJ8/TkBzIyNctqI/AAAAAAAACrg/WXVjf_-Eqo8/s400/middle6.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5638633328222189218" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;UITableViewScrollPositionMiddleの場合は特にsection header / section footer関係なく、中央に選択された行が来るようにスクロールするようです。&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;UITableViewScrollPositionBottomを指定してスクロール&lt;/span&gt;&lt;br /&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;section0, row0&lt;/td&gt;&lt;td&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-GHUDpVBSjU0/TkB1tGgD4XI/AAAAAAAACro/diGvZBitTig/s1600/bottom1.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 213px; height: 400px;" src="http://2.bp.blogspot.com/-GHUDpVBSjU0/TkB1tGgD4XI/AAAAAAAACro/diGvZBitTig/s400/bottom1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5638636151167508850" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;section0, row1&lt;/td&gt;&lt;td&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-D-yJfL-9HLE/TkB1tJzC_lI/AAAAAAAACrw/0f-eeHVvkio/s1600/bottom2.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 213px; height: 400px;" src="http://1.bp.blogspot.com/-D-yJfL-9HLE/TkB1tJzC_lI/AAAAAAAACrw/0f-eeHVvkio/s400/bottom2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5638636152052448850" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;section0, row2&lt;/td&gt;&lt;td&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-_yqoqodiaho/TkB1tVwkRUI/AAAAAAAACr4/LGzySTfAvcQ/s1600/bottom3.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 213px; height: 400px;" src="http://4.bp.blogspot.com/-_yqoqodiaho/TkB1tVwkRUI/AAAAAAAACr4/LGzySTfAvcQ/s400/bottom3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5638636155263272258" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;section1, row0&lt;/td&gt;&lt;td&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-lpyJlGycIqs/TkB11x7G_eI/AAAAAAAACsA/LBDVh9nrEdY/s1600/bottom4.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 213px; height: 400px;" src="http://4.bp.blogspot.com/-lpyJlGycIqs/TkB11x7G_eI/AAAAAAAACsA/LBDVh9nrEdY/s400/bottom4.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5638636300262637026" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;section1, row1&lt;/td&gt;&lt;td&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-3UpPDIHnDRI/TkB12OTvK8I/AAAAAAAACsI/xDPgCucwDe8/s1600/bottom5.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 213px; height: 400px;" src="http://2.bp.blogspot.com/-3UpPDIHnDRI/TkB12OTvK8I/AAAAAAAACsI/xDPgCucwDe8/s400/bottom5.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5638636307882126274" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/td&gt;&lt;td&gt;section1, row2&lt;/td&gt;&lt;td&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-nwe1Fx7hHMg/TkB12GyMJrI/AAAAAAAACsQ/97JQ5Ct8Kik/s1600/bottom6.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 213px; height: 400px;" src="http://3.bp.blogspot.com/-nwe1Fx7hHMg/TkB12GyMJrI/AAAAAAAACsQ/97JQ5Ct8Kik/s400/bottom6.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5638636305862370994" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;UITableViewScrollPositionBottomを指定すると、sectionの一番下のrowが指定された場合のみ、そのsectionのsection footerの高さを考慮してスクロールするようになります。&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-799318523892110028?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/799318523892110028/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=799318523892110028' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/799318523892110028'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/799318523892110028'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/08/uitableviewcontroller.html' title='[UITableViewController scrollToRowAtIndexPath:atScrollPosition:animated:] の挙動まとめ'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-nsoX1Acu4Bs/TkBwQh_a0oI/AAAAAAAACqQ/9M9k73ytLSU/s72-c/default.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-8400514093810399196</id><published>2011-08-05T17:11:00.004+09:00</published><updated>2011-09-07T23:05:13.258+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iPhone'/><category scheme='http://www.blogger.com/atom/ns#' term='iPad'/><category scheme='http://www.blogger.com/atom/ns#' term='設計'/><category scheme='http://www.blogger.com/atom/ns#' term='Cocoa'/><title type='text'>自分流 View Controllerの作り方 その2</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-7Iyb86XAyBo/Tjul3UhbZ-I/AAAAAAAACqI/9vjyj3gQ4d4/s1600/viewcontroller2.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 319px; height: 400px;" src="http://2.bp.blogspot.com/-7Iyb86XAyBo/Tjul3UhbZ-I/AAAAAAAACqI/9vjyj3gQ4d4/s400/viewcontroller2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5637281728404613090" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://akisute.com/2011/08/view-controller-1.html"&gt;その1はこちら&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;ぼくのかんがえたさいきょうのせっけいです&lt;br /&gt;主に以下の書籍に影響受けまくりであります&lt;br /&gt;&lt;table  border="0" cellpadding="5"&gt;&lt;tr&gt;&lt;td valign="top"&gt;&lt;a href="http://www.amazon.co.jp/Enterprise-Application-Architecture-Addison-Wesley-Signature/dp/0321127420%3FSubscriptionId%3D15SMZCTB9V8NGR2TW082%26tag%3Dakisutesama-22%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D0321127420" target="_blank"&gt;&lt;img src="http://ecx.images-amazon.com/images/I/511D6FdsbXL._SL160_.jpg" border="0" alt="0321127420" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;font size="-1"&gt;&lt;a href="http://www.amazon.co.jp/Enterprise-Application-Architecture-Addison-Wesley-Signature/dp/0321127420%3FSubscriptionId%3D15SMZCTB9V8NGR2TW082%26tag%3Dakisutesama-22%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D0321127420" target="_blank"&gt;Patterns of Enterprise Application Architecture (Addison-Wesley Signature Series (Fowler))&lt;/a&gt;&lt;img src="http://www.assoc-amazon.jp/e/ir?t=akisutesama-22&amp;l=ur2&amp;o=9" width="1" height="1" style="border: none;" alt="" /&gt;&lt;br /&gt;Martin Fowler &lt;br /&gt;Addison-Wesley Professional  2002-11-05&lt;br /&gt;&lt;br /&gt;&lt;/font&gt;&lt;font size="-2"&gt;by &lt;a href="http://www.goodpic.com/mt/aws/index.html" &gt;G-Tools&lt;/a&gt;&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;table  border="0" cellpadding="5"&gt;&lt;tr&gt;&lt;td valign="top"&gt;&lt;a href="http://www.amazon.co.jp/%E3%83%AC%E3%82%AC%E3%82%B7%E3%83%BC%E3%82%B3%E3%83%BC%E3%83%89%E6%94%B9%E5%96%84%E3%82%AC%E3%82%A4%E3%83%89-Object-Oriented-SELECTION-%E3%83%9E%E3%82%A4%E3%82%B1%E3%83%AB%E3%83%BBC%E3%83%BB%E3%83%95%E3%82%A7%E3%82%B6%E3%83%BC%E3%82%BA/dp/4798116831%3FSubscriptionId%3D15SMZCTB9V8NGR2TW082%26tag%3Dakisutesama-22%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D4798116831" target="_blank"&gt;&lt;img src="http://ecx.images-amazon.com/images/I/51MtlVCi45L._SL160_.jpg" border="0" alt="4798116831" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;font size="-1"&gt;&lt;a href="http://www.amazon.co.jp/%E3%83%AC%E3%82%AC%E3%82%B7%E3%83%BC%E3%82%B3%E3%83%BC%E3%83%89%E6%94%B9%E5%96%84%E3%82%AC%E3%82%A4%E3%83%89-Object-Oriented-SELECTION-%E3%83%9E%E3%82%A4%E3%82%B1%E3%83%AB%E3%83%BBC%E3%83%BB%E3%83%95%E3%82%A7%E3%82%B6%E3%83%BC%E3%82%BA/dp/4798116831%3FSubscriptionId%3D15SMZCTB9V8NGR2TW082%26tag%3Dakisutesama-22%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D4798116831" target="_blank"&gt;レガシーコード改善ガイド (Object Oriented SELECTION)&lt;/a&gt;&lt;img src="http://www.assoc-amazon.jp/e/ir?t=akisutesama-22&amp;l=ur2&amp;o=9" width="1" height="1" style="border: none;" alt="" /&gt;&lt;br /&gt;マイケル・C・フェザーズ ウルシステムズ株式会社 &lt;br /&gt;翔泳社  2009-07-14&lt;br /&gt;&lt;br /&gt;&lt;/font&gt;&lt;font size="-2"&gt;by &lt;a href="http://www.goodpic.com/mt/aws/index.html" &gt;G-Tools&lt;/a&gt;&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;hr/&gt;図を適当に補足&lt;br /&gt;ViewWrapperは既存のすでにあるどうしようもない設計のViewを何とか救いたいときに非常に便利、Wraper / Decoratorパターンを適用してボタンのタップを奪い取ってViewHelperに流すみたいな役目をする&lt;br /&gt;ViewHelperは簡単に言うならUITableViewControllerのdelegate, datasourceだけを担うオブジェクトみたいな感じ。要するにView専用のドメインロジックを書くオブジェクト&lt;br /&gt;Viewの表示を制御するドメインロジックが途方もなく大きくてViewControllerに納めるのが不可能になってしまったときに超便利&lt;br /&gt;&lt;br /&gt;Serviceは準ドメインロジックだと思っている、たいていの場合セミシングルトンみたいにする（通信が絡むので複数画面をまたいで使うことがほとんど）&lt;br /&gt;Androidの場合はここ、普通にServiceクラスでいいんじゃないでしょうかね&lt;br /&gt;&lt;br /&gt;Managerはドメインロジックというよりもプロセス外へのリソースアクセスを行うためのクラスというイメージ、個人的にはゲートウェイみたいな感じ&lt;ul&gt;&lt;li&gt;NSFileManager&lt;/li&gt;&lt;li&gt;NSUserDefaults&lt;/li&gt;&lt;li&gt;KeychainAccessManager&lt;/li&gt;&lt;li&gt;InAppPurchaseManager&lt;/li&gt;&lt;li&gt;APIConnectionManager&lt;/li&gt;&lt;/ul&gt;Modelはドメインモデルです、ほとんどの場合はCoreDataのNSManagedObject。用がないときでもCoreData使っておけ（超便利）&lt;br /&gt;と思ってましたがCoreDataのモデルは特にN:N関係を正しく扱わないと簡単に問題が発生してしまいますので、安易に採用すると危険かも。&lt;br /&gt;&lt;br /&gt;Task, Operationってのは非同期で実行されていく特別なドメインロジックのイメージ。要するにAPI通信みたいなもんです&lt;br /&gt;API通信を複数束ねて使ったりとか並列実行したりとかの制御が絶対必要になるのでそういうときに使う via @monjudoh&lt;pre class="prettyprint linenums"&gt;// MyTaskが終わったらMySuperTaskを実行して、それが終わったらさらにMySuperDuperTaskを連続して実行したい&lt;br /&gt;// 終わったらselfに通知させたい&lt;br /&gt;Task *root = [[[MyTask alloc] init] autorelease];&lt;br /&gt;root.nextTask = [[[MySuperTask alloc] init] autorelease];&lt;br /&gt;root.nextTask.nextTask = [[[MySuperDuperTask alloc] initWithId:100] autorelease];&lt;br /&gt;root.delegate = self;&lt;br /&gt;[root start];&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-8400514093810399196?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/8400514093810399196/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=8400514093810399196' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/8400514093810399196'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/8400514093810399196'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/08/view-controller-2.html' title='自分流 View Controllerの作り方 その2'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-7Iyb86XAyBo/Tjul3UhbZ-I/AAAAAAAACqI/9vjyj3gQ4d4/s72-c/viewcontroller2.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-7573452371022921985</id><published>2011-08-05T16:42:00.003+09:00</published><updated>2011-08-05T17:15:52.014+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iPhone'/><category scheme='http://www.blogger.com/atom/ns#' term='iPad'/><category scheme='http://www.blogger.com/atom/ns#' term='設計'/><category scheme='http://www.blogger.com/atom/ns#' term='Cocoa'/><title type='text'>自分流 View Controllerの作り方 その1</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-j22LsCtKAeA/TjugsrZ3uQI/AAAAAAAACqA/76I6bPK9ypM/s1600/viewcontroller1.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 319px; height: 400px;" src="http://3.bp.blogspot.com/-j22LsCtKAeA/TjugsrZ3uQI/AAAAAAAACqA/76I6bPK9ypM/s400/viewcontroller1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5637276048010230018" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://akisute.com/2011/08/view-controller-2.html"&gt;その2はこちら&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;以前勉強会の際に発表した View Controller の作り方のメモをまとめてみました。あくまでメモなので中身はうまくまとまっていませんが、何かのご参考になればと思います。&lt;br /&gt;&lt;br /&gt;&lt;hr/&gt;&lt;br /&gt;&lt;br /&gt;通信が絡んでくると、たいていの人がやりがちな問題（実例）&lt;ul&gt;&lt;li&gt;API通信のレスポンスを処理するコードがViewControllerの中に入っている&lt;/li&gt;&lt;li&gt;API通信が3種類必要で、Aを実行したあとにBとCを実行しなければならないとか&lt;/li&gt;&lt;li&gt;ABCのレスポンスJSONのパースまでViewControllerでやっている&lt;/li&gt;&lt;li&gt;というかAPIの呼び出しの組み立てだとかURLの指定だとか自体がIBActionの中に入っていたりする&lt;/li&gt;&lt;/ul&gt;API通信だけじゃなくてIn App Purchaseなどでも同様の事例が見られる&lt;br /&gt;&lt;br /&gt;それに対する対応策。そもそもなぜこのような問題が発生するのか？&lt;ol&gt;&lt;li&gt;Outletの生成・更新・レイアウトが分離されていない&lt;ul&gt;&lt;li&gt;そのため複数回画面が更新されるタイミングが発生するととたんに破綻する&lt;/li&gt;&lt;li&gt;大変よく見かける初心者コードが"drawXXX"という名前のOutletを生成してデータをセットしてframeまでセットして画面に配置するコード&lt;/li&gt;&lt;li&gt;Outletを描画コードと勘違いしている。Outletはペンやブラシに相当するものであって、実際に線を書くコードではない&lt;/li&gt;&lt;li&gt;この初心者コードでも動く唯一の理由は画面が一回（viewWillAppear時）しか更新されないから&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;通信という（比較的大きくなりがちな）ドメインロジックがViewControllerに混入している&lt;/li&gt;&lt;/ol&gt;そこで問題1.に対応するためにViewControllerの中でやる作業を以下のように分割する&lt;ul&gt;&lt;li&gt;Outletを生成する&lt;ul&gt;&lt;li&gt;preload（一度に生成する方法）&lt;/li&gt;&lt;li&gt;lazy load（必要になったら生成し、必要でなくなったら捨てる方法）&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Outletのプロパティを更新する&lt;/li&gt;&lt;li&gt;Outletをレイアウトする&lt;/li&gt;&lt;/ul&gt;これらはそれぞれ（基本的に）以下のようなUIViewControllerのメソッドが対応する&lt;ul&gt;&lt;li&gt;loadView&lt;ul&gt;&lt;li&gt;Outletをpreloadする場合はコレで全く問題ない。このとき、self.viewとここで作られたOutletの生存期間は等しくなる&lt;/li&gt;&lt;li&gt;Outletをlazy loadする場合はOutletを生成するコードと削除するコードを用意しておいて、必要なタイミングで呼び出すとかする&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;なし&lt;ul&gt;&lt;li&gt;プロパティを更新するために、たとえばupdateOutletsみたいなメソッドを自分で用意してやる&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;各種willRotate...系メソッド&lt;ul&gt;&lt;li&gt;willRotateほげほげの中にレイアウトコードを入れておくと自動的に画面の回転にも対応できて超便利&lt;/li&gt;&lt;li&gt;自動的に必要なタイミングで適切に呼び出ししてくれて超便利&lt;/li&gt;&lt;li&gt;そういうのが嫌いな人はlayoutOutletsForInterfaceOrientation:みたいなメソッドでも作ればいいんじゃないでしょうか&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;次に問題2.に対応するためにAPIの呼び出しやファイルアクセスなどはService, Managerなどの層を作ってそちらに任せる&lt;br /&gt;決してViewControllerの中にドメインロジックを混入させないのが大事&lt;br /&gt;→混入するとドメインロジックとビューナビゲーションロジックが混ざって大爆発する&lt;br /&gt;→さらにドメインロジック自身も複雑な通信が必要になると大爆発する&lt;br /&gt;&lt;br /&gt;それとは別にイベントを受け取ってViewの状態を制御する大事なお仕事をする必要がある&lt;ul&gt;&lt;li&gt;ボタンタップしたり&lt;/li&gt;&lt;li&gt;画面をタップしたりパンしたり&lt;/li&gt;&lt;li&gt;スクロールが発生したり&lt;/li&gt;&lt;li&gt;APIコールが完了したり&lt;/li&gt;&lt;li&gt;In App Purchaseが完了したり&lt;/li&gt;&lt;/ul&gt;ここまでがView Controllerのお仕事。決してドメインロジックを混ぜないのがポイント&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-7573452371022921985?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/7573452371022921985/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=7573452371022921985' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/7573452371022921985'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/7573452371022921985'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/08/view-controller-1.html' title='自分流 View Controllerの作り方 その1'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-j22LsCtKAeA/TjugsrZ3uQI/AAAAAAAACqA/76I6bPK9ypM/s72-c/viewcontroller1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-4232227781022360811</id><published>2011-07-31T16:30:00.002+09:00</published><updated>2011-07-31T16:34:21.164+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Xcode 4.0.2'/><category scheme='http://www.blogger.com/atom/ns#' term='Objective-C'/><title type='text'>Objective-C で文字列リテラルに \0 を含めたいときの作戦</title><content type='html'>Xcode 4.0 から LLVM が標準のコンパイラとなり、各種警告が非常に厳しくなっています。その中でも特に今回は文字列リテラルに \0 が含まれているときの警告について回避策を発見したのでご紹介したいと思います。&lt;br /&gt;&lt;br /&gt;Objective-C では文字列リテラルは @"abesi" のように @"" で囲んで表現します。このリテラルは（あくまで推測で確定ではないのですが）コンパイラによってコンパイル時に CFSTR("abesi") に置換され、 CFStringRef 型としてプログラム中に定義されているようです。さて問題はここからで、 Xcode 4.0 が内部的に構文解析のために使っている LLVM がこのリテラル中に \0 、要するにNULL文字が含まれていると以下のような警告を出すようになってしまったのです&lt;blockquote&gt;CFString literal contains NUL character&lt;/blockquote&gt;普通はNULL文字をリテラル中に含めたいということはまず無いのですが、SMTPの通信部分を書いたりしていると通信プロトコル自体が命令を \0 で区切れみたいな要件を求めてくるため、どうしてもリテラルの中に \0 を含めたいときが出てきます。 まぁ、具体的には以下のライブラリなんですけどね。&lt;br /&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/skpsmtpmessage/source/browse/trunk/SMTPSender/Classes/SKPSMTPMessage.m"&gt;http://code.google.com/p/skpsmtpmessage/source/browse/trunk/SMTPSender/Classes/SKPSMTPMessage.m&lt;/a&gt;&lt;pre class="prettyprint linenums"&gt;sendState = kSKPSMTPWaitingAuthSuccess;&lt;br /&gt;NSString *loginString = [NSString stringWithFormat:@"\000%@\000%@", login, pass];&lt;br /&gt;NSString *authString = [NSString stringWithFormat:@"AUTH PLAIN %@\r\n", [[loginString dataUsingEncoding:NSUTF8StringEncoding] encodeBase64ForData]];&lt;br /&gt;NSLog(@"C: %@", authString);&lt;br /&gt;if (CFWriteStreamWriteFully((CFWriteStreamRef)outputStream, (const uint8_t *)[authString UTF8String], [authString lengthOfBytesUsingEncoding:NSUTF8StringEncoding]) &lt; 0)&lt;br /&gt;{&lt;br /&gt;    error =  [outputStream streamError];&lt;br /&gt;    encounteredError = YES;&lt;br /&gt;}&lt;br /&gt;else&lt;br /&gt;{&lt;br /&gt;    [self startShortWatchdog];&lt;br /&gt;}&lt;/pre&gt;そして私と同じライブラリの同じ箇所でぶつかった人を発見。&lt;br /&gt;&lt;br /&gt;&lt;a href="http://stackoverflow.com/questions/5814520/how-do-i-create-a-login-string-that-contains-2-embedded-nulls-and-the-login-an"&gt;http://stackoverflow.com/questions/5814520/how-do-i-create-a-login-string-that-contains-2-embedded-nulls-and-the-login-an&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;さて回避方法はないものかと探してみたところ、ちょうど良い回避策が発見できました。&lt;br /&gt;&lt;br /&gt;&lt;a href="http://stackoverflow.com/questions/6211908/nsstring-with-0"&gt;http://stackoverflow.com/questions/6211908/nsstring-with-0&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;NSStringのstringWithFormat:に %C を埋め込んで、そこに 0 を渡せばうまくいくみたいです！&lt;pre class="prettyprint linenums"&gt;int main() {&lt;br /&gt;    NSString *string = [NSString stringWithFormat: @"Hello%CWorld!", 0];&lt;br /&gt;    NSData *bytes = [string dataUsingEncoding: NSUTF8StringEncoding];&lt;br /&gt;    NSLog(@"string: %@", string);&lt;br /&gt;    NSLog(@"bytes: %@", bytes);&lt;br /&gt;    return 0;&lt;br /&gt;}&lt;/pre&gt;さっきの例だと、&lt;pre class="prettyprint linenums"&gt;sendState = kSKPSMTPWaitingAuthSuccess;&lt;br /&gt;NSString *loginString = [NSString stringWithFormat:@"%C%@%C%@", 0, login, 0, pass];&lt;br /&gt;NSString *authString = [NSString stringWithFormat:@"AUTH PLAIN %@\r\n", [[loginString dataUsingEncoding:NSUTF8StringEncoding] encodeBase64ForData]];&lt;br /&gt;NSLog(@"C: %@", authString);&lt;br /&gt;if (CFWriteStreamWriteFully((CFWriteStreamRef)outputStream, (const uint8_t *)[authString UTF8String], [authString lengthOfBytesUsingEncoding:NSUTF8StringEncoding]) &lt; 0)&lt;br /&gt;{&lt;br /&gt;    error =  [outputStream streamError];&lt;br /&gt;    encounteredError = YES;&lt;br /&gt;}&lt;br /&gt;else&lt;br /&gt;{&lt;br /&gt;    [self startShortWatchdog];&lt;br /&gt;}&lt;/pre&gt;このようにすればばっちり上手く回避できました！&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-4232227781022360811?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/4232227781022360811/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=4232227781022360811' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/4232227781022360811'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/4232227781022360811'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/07/objective-c-0.html' title='Objective-C で文字列リテラルに \0 を含めたいときの作戦'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-1989588631183390719</id><published>2011-07-18T14:34:00.002+09:00</published><updated>2011-07-18T14:39:07.095+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='iPad'/><category scheme='http://www.blogger.com/atom/ns#' term='Twitter'/><category scheme='http://www.blogger.com/atom/ns#' term='iOS 4.3.3'/><category scheme='http://www.blogger.com/atom/ns#' term='Cookie'/><title type='text'>iPad の UIWebView で twitter.com を表示したときに出てくるアプリの宣伝広告を出さない方法</title><content type='html'>iOS　アプリ内で Twitter のタイムラインを表示したり、投稿させたり、 &lt;a href="http://twitter.com/about/resources/tweetbutton"&gt;Tweet Button&lt;/a&gt; を置きたいみたいな要求は結構あると思うのですが、ここで問題になるのが iPad の UIWebViewで twitter.com を表示したときです。以下の画像のように、 Twitter for iPad をオススメする広告が最初に表示されてしまうのです。&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-BDyzI6CzWjw/TiPGRBCFokI/AAAAAAAACpg/7o0CbSAwssM/s1600/twitter_ipad_1.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 300px;" src="http://3.bp.blogspot.com/-BDyzI6CzWjw/TiPGRBCFokI/AAAAAAAACpg/7o0CbSAwssM/s400/twitter_ipad_1.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5630561954780521026" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;一度 Continue on mobile.twitter.com ボタンを押せば次の画面に遷移して二度と表示されなくなるのですが、大帝のお客さんはこの画面を見た瞬間意味不明になってしまうと思うので、表示されないようにしなければなりません。&lt;br /&gt;&lt;br /&gt;最初に思いついた方法は以下の&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-K7oGjP3AgxU/TiPGReeltBI/AAAAAAAACpo/I8dkTB-nPXU/s1600/twitter_ipad_2.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 300px;" src="http://4.bp.blogspot.com/-K7oGjP3AgxU/TiPGReeltBI/AAAAAAAACpo/I8dkTB-nPXU/s400/twitter_ipad_2.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5630561962684691474" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://mobile.twitter.com/settings/dismiss?d=2"&gt;http://mobile.twitter.com/settings/dismiss?d=2&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;このリンクを　NSHTTPConnection なんかで踏ませればいいんじゃないかと思っていたのですが、調査してみた結果もっと簡単に何とかできることがわかりました。このアプリの宣伝広告を消すのに一番簡単な方法は、以下のように Cookie をセットしてやることです。&lt;pre class="prettyprint linenums"&gt;// mobile.twitter.comにUIWebViewからアクセスしたときに、"Get Twitter for iPad NOW"とかなんとか表示されるのを防ぐため、&lt;br /&gt;// UIWebViewが使うcookieにd=2をセットしておく&lt;br /&gt;// NSHTTPCookieExpiresはセットしなくても大丈夫です（その場合起動ごとにCookieがけされてしまうので、起動時に毎回セットしてください）&lt;br /&gt;NSHTTPCookie *twitterForIPadAdBlockCookie = [NSHTTPCookie cookieWithProperties:[NSDictionary dictionaryWithObjectsAndKeys:&lt;br /&gt;                                                                                @"d", NSHTTPCookieName,&lt;br /&gt;                                                                                @"2", NSHTTPCookieValue,&lt;br /&gt;                                                                                @".twitter.com", NSHTTPCookieDomain,&lt;br /&gt;                                                                                @"/", NSHTTPCookiePath,&lt;br /&gt;                                                                                [NSDate distantFuture], NSHTTPCookieExpires,&lt;br /&gt;                                                                                nil]];&lt;br /&gt;[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:twitterForIPadAdBlockCookie];&lt;/pre&gt;これだけでご覧の通り！嘘のように広告が出なくなります。&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-M6qT7izE_9w/TiPGRSGV6WI/AAAAAAAACpw/SxpGVU8Xs3Y/s1600/twitter_ipad_3.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 300px;" src="http://4.bp.blogspot.com/-M6qT7izE_9w/TiPGRSGV6WI/AAAAAAAACpw/SxpGVU8Xs3Y/s400/twitter_ipad_3.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5630561959361767778" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■おまけ: javascript:スキームを使ってみよう&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;今回のように UIWebView をアプリ内で使って特定のWebアプリを表示する場合にWebアプリの挙動が知りたくなったときは、iPadのSafariブラウザから javascript: スキームを使って JavaScript のコードを流し込んでデバッグするとなかなかはかどると言うことがわかりました。たとえばクッキーを表示させてやるだけなら、以下のように超簡単にできます:&lt;pre&gt;javascript:alert(document.cookie);&lt;/pre&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-1vI3dJRP5dk/TiPGRrLaLBI/AAAAAAAACp4/fzVq5PEGqjA/s1600/twitter_ipad_4.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 300px;" src="http://2.bp.blogspot.com/-1vI3dJRP5dk/TiPGRrLaLBI/AAAAAAAACp4/fzVq5PEGqjA/s400/twitter_ipad_4.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5630561966093904914" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;クッキーを流し込むのも、流し込むだけならこれまた簡単:&lt;pre&gt;javascript:document.cookie="foo=bar";&lt;/pre&gt;より詳細な調査はPC側のブラウザでゆっくりやって、最後にちょっとだけ試したいところを実機でやってみることができるのがいい感じです。多分この用途のためのブラウザアプリなんかも App Store をあされば出てくると思うので、そういうのを使えばさらにはかどると思います。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-1989588631183390719?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/1989588631183390719/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=1989588631183390719' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/1989588631183390719'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/1989588631183390719'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/07/ipad-uiwebview-twittercom.html' title='iPad の UIWebView で twitter.com を表示したときに出てくるアプリの宣伝広告を出さない方法'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-BDyzI6CzWjw/TiPGRBCFokI/AAAAAAAACpg/7o0CbSAwssM/s72-c/twitter_ipad_1.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-8313022881713146013</id><published>2011-07-18T13:56:00.002+09:00</published><updated>2011-07-18T14:04:30.109+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='勉強会'/><category scheme='http://www.blogger.com/atom/ns#' term='Cocoa'/><title type='text'>BPStudy #46 での発表資料 ViewController の作り方を公開してます</title><content type='html'>かなり旧聞になってしまいますが、 BPStudy #46 で話したときの資料をpreziにアップしてますので、ご覧いただけます。&lt;br /&gt;&lt;a href="http://prezi.com/7b_joy2lcfil/bpstudy-46/"&gt;http://prezi.com/7b_joy2lcfil/bpstudy-46/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;発表時にお見せしたソースコードはちょっと公開出来なかったのでこの資料だけだとイマイチよくわからないのですが、要するに&lt;ul&gt;&lt;li&gt;View Controllerにサービスを書かないようにしてサービスレイヤを分離しろ&lt;/li&gt;&lt;li&gt;View Controllerの描画コードは、アウトレットの生成、アウトレットのデータ更新、アウトレットのレイアウトの3つに分離しろ&lt;/li&gt;&lt;/ul&gt;って言う感じのお話をしました。&lt;br /&gt;&lt;br /&gt;すげー当たり前のことしか書いてなくて恐縮なのですが＞＜&lt;br /&gt;実際、人様のコードをメンテしたりバージョンアップしたりするお仕事をいただいていると、ほとんど全てのコードがこの問題に引っかかっていて非同期通信化すると動かないとかちょっとView Controllerの呼び出され方を変えると動かないとかあって、iOS開発者の皆さんがこういうところに気を配ってコードを書いていただければなぁ&lt;del&gt;そして私が楽できればなぁ&lt;/del&gt;という思いで書いてみた次第であります。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-8313022881713146013?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/8313022881713146013/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=8313022881713146013' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/8313022881713146013'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/8313022881713146013'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/07/bpstudy-46-viewcontroller.html' title='BPStudy #46 での発表資料 ViewController の作り方を公開してます'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-4906722462225041817</id><published>2011-06-21T21:22:00.002+09:00</published><updated>2011-06-21T21:29:55.135+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='セキュリティ'/><title type='text'>Netlogがハックしたgmailアカウントの情報を用いてspamを送っている？</title><content type='html'>やや旧聞になるのですが、お恥ずかしながらgmailのアカウントが何らかの手段によってハックされてしまったようで、私のメールアドレスから大量のspamが連絡先に飛んでしまう事件がありました。関係者の皆様には大変ご迷惑をおかけいたしまして誠にすみません＞＜&lt;br /&gt;&lt;br /&gt;パスワードは標準以上に強固だったはず（ハックされたアカウントが使っていたパスワードは10桁で大文字小文字数字記号全てランダムに混ざったもの）なのですが、マルウェアも見つからないし心当たりのあるフィッシング被害もないしPSNには登録してないし・・・ということでまったくどこからやられたのかわかりません。恐ろしいです。パスワードだけではもはや不十分ということかも知れません。&lt;br /&gt;&lt;br /&gt;さてここからが本題。&lt;br /&gt;Netlog (http://ja.netlog.com/) というSNSがあるのですが、今週の月曜日に知人から続々Netlogへの勧誘メールが私から飛んできたという報告が。&lt;br /&gt;&lt;br /&gt;手口はどうも私のgmailの連絡先に入っていたメールアドレスに対して、私がin-reply-toになるようなspamを次々送りつけるというもののようです。他の経路からspamされているのではと思って調べてみたのですが、一番怪しいFacebookについてもセキュリティが破られた形跡はないし、そもそも一度もNetlogなるサービスを聞いたこともないしページを開いたことも友達に勧められたこともありません。さらに私のgmailの連絡先にしか入っていないメールアドレスにもspamが飛んでいるようで、どうもこの盗まれたアカウント情報を元にspamを送っているような気がしてなりません。&lt;br /&gt;&lt;br /&gt;あくまで状況証拠なのですが、ともかく皆さんもgmailのセキュリティには万全を期してください＞＜&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-4906722462225041817?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/4906722462225041817/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=4906722462225041817' title='5 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/4906722462225041817'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/4906722462225041817'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/06/netloggmailspam.html' title='Netlogがハックしたgmailアカウントの情報を用いてspamを送っている？'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-2597985786728646732</id><published>2011-05-29T17:10:00.008+09:00</published><updated>2011-05-29T17:51:24.332+09:00</updated><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='iPad'/><category scheme='http://www.blogger.com/atom/ns#' term='スタイラス'/><title type='text'>iPhone iPad 向けスタイラスで書き味勝負をしてみた 2回戦</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-0EpOKl4LS6Q/TeIAU-VjlVI/AAAAAAAACmk/nw3YYmZvCG4/s1600/styluses.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 300px;" src="http://3.bp.blogspot.com/-0EpOKl4LS6Q/TeIAU-VjlVI/AAAAAAAACmk/nw3YYmZvCG4/s400/styluses.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5612048445987853650" /&gt;&lt;/a&gt;&lt;br /&gt;写真は左から順に、 &lt;a href="http://tenonedesign.com/sketch.php"&gt;Pogo Sketch&lt;/a&gt; 、 &lt;a href="http://ostylus.com/"&gt;oStylus 初期限定生産型&lt;/a&gt; 、 &lt;a href="http://www.amazon.co.jp/%E3%83%91%E3%83%AF%E3%83%BC%E3%82%B5%E3%83%9D%E3%83%BC%E3%83%88-PBJ-91-%E3%82%B9%E3%83%9E%E3%83%BC%E3%83%88%E3%83%9A%E3%83%B3-%E3%82%B7%E3%83%AB%E3%83%90%E3%83%BC/dp/B004I8X4O4%3FSubscriptionId%3D15SMZCTB9V8NGR2TW082%26tag%3Dakisutesama-22%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3DB004I8X4O4"&gt;パワーサポート スマートペン PBJ-9Xシリーズ&lt;/a&gt; 、 &lt;a href="http://www.amazon.co.jp/iPhone4%E5%AF%BE%E5%BF%9C-%E6%8F%8F%E7%94%BB%E3%80%81%E3%83%9D%E3%82%A4%E3%83%B3%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%E3%81%AB%E6%9C%80%E9%81%A9%E3%81%AA%E3%82%BF%E3%83%83%E3%83%81%E3%83%9A%E3%83%B3-Bamboo-CS-100-K0/dp/B004XF0FQW%3FSubscriptionId%3D15SMZCTB9V8NGR2TW082%26tag%3Dakisutesama-22%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3DB004XF0FQW"&gt;Bamboo Stylus&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;iPhone/iPad向けのスタイラスがいくつも発売されていますが、実際にスタイラスを使ったらどんな具合なの？指でいいんじゃないの？と疑問をお持ちの方と、 &lt;span style="font-weight:bold;"&gt;私のようなスタイラスマニアの方&lt;/span&gt; のために、iPhone/iPad向けのスタイラスの書き味を実際に書いてみて試してみるという企画です。&lt;br /&gt;&lt;br /&gt;前回の記事はこちら: &lt;a href="http://akisute.com/2011/02/iphone-ipad.html"&gt;http://akisute.com/2011/02/iphone-ipad.html&lt;/a&gt;&lt;br /&gt;おすすめスタイラスまとめ記事はこちら: &lt;a href="http://akisute.com/2010/06/ipad.html"&gt;http://akisute.com/2010/06/ipad.html&lt;/a&gt;&lt;br /&gt;Bamboo Stylusのレビューはこちら: &lt;a href="http://akisute.com/2011/05/ipad-bamboo-stylus.html"&gt;http://akisute.com/2011/05/ipad-bamboo-stylus.html&lt;/a&gt;&lt;br /&gt;oStylusのレビューはこちら: &lt;a href="http://akisute.com/2010/10/ipad-ostylus.html"&gt;http://akisute.com/2010/10/ipad-ostylus.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■比較方法&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;iPad上で実際にスタイラスでいろいろ書いてみて、書き味を見て比較します。&lt;ul&gt;&lt;li&gt;使用するiPadは &lt;a href="http://www.apple.com/jp/ipad/specs/"&gt;iPad 2 Black 16GB (WiFi+3G GSM)&lt;/a&gt;&lt;ul&gt;&lt;li&gt;表面に保護フィルムは貼っていません&lt;/li&gt;&lt;li&gt;保護フィルムがある場合、保護フィルムのためにペン先の滑りおよび感度が変化するため、結果が異なってくる可能性があります。&lt;/li&gt;&lt;li&gt;一般的に、保護フィルムがある方が感度が悪くなります。滑りはフィルムの材質により変化します。&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;使用するアプリは &lt;a href="http://itunes.apple.com/jp/app/noteshelf/id392188745?mt=8&amp;uo=4" target="itunes_store"&gt;Noteshelf&lt;/a&gt;&lt;ul&gt;&lt;li&gt;無地ノート&lt;/li&gt;&lt;li&gt;黒インク&lt;/li&gt;&lt;li&gt;ペン先10pt&lt;/li&gt;&lt;li&gt;拡大は使用しない&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;すべて一発勝負&lt;ul&gt;&lt;li&gt;undoなし&lt;/li&gt;&lt;li&gt;書き損じたり、ペン先の感度が落ちて線が飛んでもやり直さない。それは感度が実際に悪いという証拠になるため。&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■結果&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;書いてみたノートをpdfにして出力してみました。以下のURLからご覧になれます。&lt;br /&gt;&lt;a href="https://docs.google.com/viewer?a=v&amp;pid=sites&amp;srcid=ZGVmYXVsdGRvbWFpbnxha2lzdXRlc2FtYXxneDo0OTI3MWU0MjRlMzI2ZjNm"&gt;https://docs.google.com/viewer?a=v&amp;pid=sites&amp;srcid=ZGVmYXVsdGRvbWFpbnxha2lzdXRlc2FtYXxneDo0OTI3MWU0MjRlMzI2ZjNm&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;複数同じ文言が並んでいるページは、全て上から順に、&lt;br /&gt;pogo sketch, oStylus, スマートペン, Bamboo Stylus&lt;br /&gt;の順に並んでいます。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■考察&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;以下、いくつかのページをピックアップして考察。&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-fN2ycT7txow/TeIDKxQTbzI/AAAAAAAACms/vuLOJxUG6vA/s1600/%25E3%2582%25B9%25E3%2582%25BF%25E3%2582%25A4%25E3%2583%25A9%25E3%2582%25B9%25E6%259B%25B8%25E3%2581%258D%25E6%25AF%2594%25E3%2581%25B9%2BP1.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 319px; height: 400px;" src="http://3.bp.blogspot.com/-fN2ycT7txow/TeIDKxQTbzI/AAAAAAAACms/vuLOJxUG6vA/s400/%25E3%2582%25B9%25E3%2582%25BF%25E3%2582%25A4%25E3%2583%25A9%25E3%2582%25B9%25E6%259B%25B8%25E3%2581%258D%25E6%25AF%2594%25E3%2581%25B9%2BP1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5612051569212354354" /&gt;&lt;/a&gt;&lt;br /&gt;pogo sketchは第一世代のスポンジ式ペン先であるため、やはりペン先感度が悪く線が飛びまくります。線自体は自然に書けているのですが。&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-3GZNDKEPeUU/TeIFJvmFR-I/AAAAAAAACm0/N6Ch6auwP28/s1600/%25E3%2582%25B9%25E3%2582%25BF%25E3%2582%25A4%25E3%2583%25A9%25E3%2582%25B9%25E6%259B%25B8%25E3%2581%258D%25E6%25AF%2594%25E3%2581%25B9%2BP2.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 319px; height: 400px;" src="http://4.bp.blogspot.com/-3GZNDKEPeUU/TeIFJvmFR-I/AAAAAAAACm0/N6Ch6auwP28/s400/%25E3%2582%25B9%25E3%2582%25BF%25E3%2582%25A4%25E3%2583%25A9%25E3%2582%25B9%25E6%259B%25B8%25E3%2581%258D%25E6%25AF%2594%25E3%2581%25B9%2BP2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5612053750610216930" /&gt;&lt;/a&gt;&lt;br /&gt;oStylusは感度はよいものの、いかんせん書きづらい。曲線が特に不自然です。しかも書くのに時間がかかります。多分一番時間がかかりました。&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-subM98GAUrM/TeIHHtDy06I/AAAAAAAACnM/Z0nxDmtflnA/s1600/%25E3%2582%25B9%25E3%2582%25BF%25E3%2582%25A4%25E3%2583%25A9%25E3%2582%25B9%25E6%259B%25B8%25E3%2581%258D%25E6%25AF%2594%25E3%2581%25B9%2BP3.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 319px; height: 400px;" src="http://1.bp.blogspot.com/-subM98GAUrM/TeIHHtDy06I/AAAAAAAACnM/Z0nxDmtflnA/s400/%25E3%2582%25B9%25E3%2582%25BF%25E3%2582%25A4%25E3%2583%25A9%25E3%2582%25B9%25E6%259B%25B8%25E3%2581%258D%25E6%25AF%2594%25E3%2581%25B9%2BP3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5612055914593047458" /&gt;&lt;/a&gt;&lt;br /&gt;スマートペンはさすがの高性能。最高の感度と軽い軸の恩恵で、一番楽に書けます。ただし線自体は細かいところが弱いです。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-5-lVvZ63AE8/TeIHHUbgJ4I/AAAAAAAACnE/Gnovn7X6cKk/s1600/%25E3%2582%25B9%25E3%2582%25BF%25E3%2582%25A4%25E3%2583%25A9%25E3%2582%25B9%25E6%259B%25B8%25E3%2581%258D%25E6%25AF%2594%25E3%2581%25B9%2BP4.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 319px; height: 400px;" src="http://2.bp.blogspot.com/-5-lVvZ63AE8/TeIHHUbgJ4I/AAAAAAAACnE/Gnovn7X6cKk/s400/%25E3%2582%25B9%25E3%2582%25BF%25E3%2582%25A4%25E3%2583%25A9%25E3%2582%25B9%25E6%259B%25B8%25E3%2581%258D%25E6%25AF%2594%25E3%2581%25B9%2BP4.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5612055907981600642" /&gt;&lt;/a&gt;&lt;br /&gt;今回新顔のBamboo Stylus。ペンが重く、スマートペンより筆圧が必要なため疲れますが、スピードのある細かい線が魅力。一番速く書けたのもこのペンです。&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-q2-3mpBJ6DQ/TeIHHEaR-tI/AAAAAAAACm8/CJayfwm39G8/s1600/%25E3%2582%25B9%25E3%2582%25BF%25E3%2582%25A4%25E3%2583%25A9%25E3%2582%25B9%25E6%259B%25B8%25E3%2581%258D%25E6%25AF%2594%25E3%2581%25B9%2BP6.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 319px; height: 400px;" src="http://2.bp.blogspot.com/-q2-3mpBJ6DQ/TeIHHEaR-tI/AAAAAAAACm8/CJayfwm39G8/s400/%25E3%2582%25B9%25E3%2582%25BF%25E3%2582%25A4%25E3%2583%25A9%25E3%2582%25B9%25E6%259B%25B8%25E3%2581%258D%25E6%25AF%2594%25E3%2581%25B9%2BP6.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5612055903681510098" /&gt;&lt;/a&gt;&lt;br /&gt;並べてみるとこんな感じです。上からpogo sketch, oStylus, スマートペン, Bamboo Stylus。良いと思ったところには緑○を、悪いと思ったところには赤×を引いています。&lt;br /&gt;pogoは線が飛びさえしなければ・・・&lt;br /&gt;oStylusはとにかく線をゆっくり引いてしまう。 Noteshelf アプリは Penultimate 同様、線を高速に引けば美しく細くなるように出来ているのですが、見てのとおり全ての線が太くてゆっくり引いてしまっている。Zとかへろへろですよ、もう。&lt;br /&gt;スマートペンとBamboo Stylusは安定して良いですね。高速に美しく書けています。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■まとめ&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;やはり第二世代のシリコンペン先を装備したスタイラスが圧倒的に良いです。その中でも自分の好みや用途で選べる次代になってきたのがすごくいいですね。次回はプリンストンテクノロジーの専用タッチペンやAcase Stylusなんかも加えてレビューしてみたいです。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-2597985786728646732?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/2597985786728646732/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=2597985786728646732' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/2597985786728646732'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/2597985786728646732'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/05/iphone-ipad-2.html' title='iPhone iPad 向けスタイラスで書き味勝負をしてみた 2回戦'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-0EpOKl4LS6Q/TeIAU-VjlVI/AAAAAAAACmk/nw3YYmZvCG4/s72-c/styluses.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-7953543331835974705</id><published>2011-05-29T15:55:00.010+09:00</published><updated>2011-05-29T16:26:47.976+09:00</updated><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='iPad'/><category scheme='http://www.blogger.com/atom/ns#' term='スタイラス'/><title type='text'>iPad 用スタイラス Bamboo Stylus を試してみた</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-2XUXIo93S2w/TeHwH9Oyg8I/AAAAAAAACmE/9q6_l3siGvE/s1600/bamboo_stylus.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 300px;" src="http://1.bp.blogspot.com/-2XUXIo93S2w/TeHwH9Oyg8I/AAAAAAAACmE/9q6_l3siGvE/s400/bamboo_stylus.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5612030630166692802" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;つい先日いよいよ発売された Bamboo Stylus, 早速買って試してみました。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■Bamboo Stylus とは？&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://wacom.jp/jp/company/news_detail.php?id=355"&gt;http://wacom.jp/jp/company/news_detail.php?id=355&lt;/a&gt;&lt;br /&gt;&lt;a href="http://japanese.engadget.com/2011/04/19/bamboo-stylus/"&gt;http://japanese.engadget.com/2011/04/19/bamboo-stylus/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;table  border="0" cellpadding="5"&gt;&lt;tr&gt;&lt;td valign="top"&gt;&lt;a href="http://www.amazon.co.jp/iPhone4%E5%AF%BE%E5%BF%9C-%E6%8F%8F%E7%94%BB%E3%80%81%E3%83%9D%E3%82%A4%E3%83%B3%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%E3%81%AB%E6%9C%80%E9%81%A9%E3%81%AA%E3%82%BF%E3%83%83%E3%83%81%E3%83%9A%E3%83%B3-Bamboo-CS-100-K0/dp/B004XF0FQW%3FSubscriptionId%3D15SMZCTB9V8NGR2TW082%26tag%3Dakisutesama-22%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3DB004XF0FQW" target="_blank"&gt;&lt;img src="http://ecx.images-amazon.com/images/I/31tKI7Rzp8L._SL160_.jpg" border="0" alt="B004XF0FQW" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;font size="-1"&gt;&lt;a href="http://www.amazon.co.jp/iPhone4%E5%AF%BE%E5%BF%9C-%E6%8F%8F%E7%94%BB%E3%80%81%E3%83%9D%E3%82%A4%E3%83%B3%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%E3%81%AB%E6%9C%80%E9%81%A9%E3%81%AA%E3%82%BF%E3%83%83%E3%83%81%E3%83%9A%E3%83%B3-Bamboo-CS-100-K0/dp/B004XF0FQW%3FSubscriptionId%3D15SMZCTB9V8NGR2TW082%26tag%3Dakisutesama-22%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3DB004XF0FQW" target="_blank"&gt;Wacom iPad/IPad2/iPhone4対応 描画、ポインティングに最適なタッチペン Bamboo Stylus CS-100/K0&lt;/a&gt;&lt;img src="http://www.assoc-amazon.jp/e/ir?t=akisutesama-22&amp;l=ur2&amp;o=9" width="1" height="1" style="border: none;" alt="" /&gt;&lt;br /&gt;ワコム  2011-05-27&lt;br /&gt;&lt;br /&gt;&lt;/font&gt;&lt;font size="-2"&gt;by &lt;a href="http://www.goodpic.com/mt/aws/index.html" &gt;G-Tools&lt;/a&gt;&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;PC向けペンタブレットではおそらく業界最大手の Wacom が、満を持して投入してきた静電誘導式タッチディスプレイ用のスタイラスペンです。ペンタブレットの開発でおそらくこの手のスタイラスペンに関しては相当なノウハウがあるのではないかと思われ、非常に期待が持てます。プレスリリースで、特に以下のような点が既存のスタイラスとは異なると強調されています。&lt;ul&gt;&lt;li&gt;手に持った時の心地よさと書きやすさを両立する重さと重心のバランス。&lt;/li&gt;&lt;li&gt;上質なサテン調のブラックとシルバー色を採用し、高い質感を実現。&lt;/li&gt;&lt;li&gt;ペン先は主な他社製品よりも直径が約25%小さく、より自然で直感的な描画が可能。&lt;/li&gt;&lt;li&gt;スムーズで快適な書き心地を実現するペン先の実現。（磨耗した際には交換が可能）&lt;/li&gt;&lt;li&gt;iPadカバーに留めたり、ポケットに留めたりするなど、携帯や保管にも便利なクリップ。（脱着可能）&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■最初に結論&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;良い点&lt;/span&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;span style="font-weight:bold;"&gt;悪い点&lt;/span&gt;&lt;ul&gt;&lt;li&gt;同サイズのスタイラスペンの中では圧倒的に重く、書く際に手が疲れる。&lt;/li&gt;&lt;li&gt;第二世代のシリコンペン先を採用している他のスタイラスペンと比べ、感度がやや悪い。&lt;/li&gt;&lt;li&gt;3000円という、やや高価な値段設定。&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■外見、持った感触&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;まずは外見から。値段設定がやや高めで、かつBambooブランドの名前を冠していることからもわかるとおり、iPad向けスタイラスとしてはハイエンドを狙っている物と思われます。そのためデザインにも力が入っており、表面がiPadやMacのように梨地加工されています。単なる金属の棒という体の &lt;a href="http://www.amazon.co.jp/%E3%83%91%E3%83%AF%E3%83%BC%E3%82%B5%E3%83%9D%E3%83%BC%E3%83%88-PBJ-91-%E3%82%B9%E3%83%9E%E3%83%BC%E3%83%88%E3%83%9A%E3%83%B3-%E3%82%B7%E3%83%AB%E3%83%90%E3%83%BC/dp/B004I8X4O4%3FSubscriptionId%3D15SMZCTB9V8NGR2TW082%26tag%3Dakisutesama-22%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3DB004I8X4O4" target="_blank"&gt;パワーサポート スマートペン&lt;/a&gt; や &lt;a href="http://www.amazon.co.jp/%E3%83%97%E3%83%AA%E3%83%B3%E3%82%B9%E3%83%88%E3%83%B3%E3%83%86%E3%82%AF%E3%83%8E%E3%83%AD%E3%82%B8%E3%83%BC-iPad-iPhone-touch%E5%B0%82%E7%94%A8%E3%82%BF%E3%83%83%E3%83%81%E3%83%9A%E3%83%B3-PIP-TP2B/dp/B003UTAOEA%3FSubscriptionId%3D15SMZCTB9V8NGR2TW082%26tag%3Dakisutesama-22%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3DB003UTAOEA" target="_blank"&gt;プリンストンテクノロジー　専用タッチペン&lt;/a&gt; に比べ断然高級感があり美しく感じられます。&lt;br /&gt;&lt;br /&gt;長さは12cmということで、他社のスタイラスと比べても数ミリ長い程度で標準的だと思います。軸は他社の製品に比べてやや太く、良くコンビニなどで売っているボールペンよりわずかに細い程度になっています。そのため手に持った際の感覚が非常にペンらしいです。また、重さが非常に特徴的で、他のスタイラスと比べて明らかに密度のある重さがあります。体感だと パワーサポート スマートペン より二倍近く重いように感じます。&lt;br /&gt;&lt;br /&gt;上部とペン先はねじになっていて、それぞれクリップとペン先が取り外せるようになっており、メンテナンスのことを考えた作りになっているのが心憎いです。消耗品ではなく、長期間使わせる物という印象を受けます。また、取り外した上部のクリップの部分にストラップをつけて持ち歩くことも出来そうです。&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-i6vpiy6MFgE/TeHwIFJie_I/AAAAAAAACmU/eibH78YgLfA/s1600/stylus_length.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 257px; height: 400px;" src="http://2.bp.blogspot.com/-i6vpiy6MFgE/TeHwIFJie_I/AAAAAAAACmU/eibH78YgLfA/s400/stylus_length.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5612030632292154354" /&gt;&lt;/a&gt;&lt;br /&gt;長さ比較。左から右に短い物順。pogo sketch, スマートペン, Bamboo Stylus, oStylus&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-ZJiQM1W9qZk/TeHwIN2wpzI/AAAAAAAACmM/eLhWR8T_JEY/s1600/stylus_diameter.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 300px;" src="http://4.bp.blogspot.com/-ZJiQM1W9qZk/TeHwIN2wpzI/AAAAAAAACmM/eLhWR8T_JEY/s400/stylus_diameter.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5612030634629310258" /&gt;&lt;/a&gt;&lt;br /&gt;太さ比較。先ほどと同じ順序。pogo sketch, スマートペン, Bamboo Stylus, oStylus&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■動作、書き味&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;買って最初に一筆書いてみた時にすぐ気づいたのが、まず感度が悪いです。ほとんど載せるだけで反応する超感度の パワーサポート スマートペン に対して、ほんの少しだけ力を込めないと反応しません。しかしながらペン先が細くてしっかりしており、iPadの表面を非常になめらかに滑ります。滑りがよいので実際に紙で書いているよりちょっと違う感じがしますが、ペンタブレットに慣れている人にはちょうどいいぐらいだと思います。先端がふにゃふにゃしてやや抵抗がある滑りの パワーサポート スマートペン とは対照的な印象です。&lt;br /&gt;&lt;br /&gt;個人的には長時間書いていると疲れます。感度が悪く抵抗が弱いのと重いペンが相まって、腕の力を使うためだと思います。&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-4sTVLEt7HGs/TeH0IP6xBZI/AAAAAAAACmc/D49nsEOgBzU/s1600/%25E3%2582%25B9%25E3%2582%25BF%25E3%2582%25A4%25E3%2583%25A9%25E3%2582%25B9%25E6%259B%25B8%25E3%2581%258D%25E6%25AF%2594%25E3%2581%25B9%2BP4.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 319px; height: 400px;" src="http://1.bp.blogspot.com/-4sTVLEt7HGs/TeH0IP6xBZI/AAAAAAAACmc/D49nsEOgBzU/s400/%25E3%2582%25B9%25E3%2582%25BF%25E3%2582%25A4%25E3%2583%25A9%25E3%2582%25B9%25E6%259B%25B8%25E3%2581%258D%25E6%25AF%2594%25E3%2581%25B9%2BP4.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5612035033229493650" /&gt;&lt;/a&gt;&lt;br /&gt;実際に &lt;a href="http://itunes.apple.com/jp/app/noteshelf/id392188745?mt=8&amp;uo=4" target="itunes_store"&gt;Noteshelf&lt;/a&gt; アプリ上で書いてみました。実際のペン同様、非常になめらかに書けています。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■まとめ&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;WacomとしてはiPad向けスタイラスのハイエンドモデルとして位置づけているこの商品ですが、実際に使ってみるとむしろ パワーサポート スマートペン と対になるような感じの印象を受けました。すなわち、以下のように棲み分けられます。&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Bamboo Stylus&lt;/span&gt; をオススメする人&lt;ul&gt;&lt;li&gt;ペンに近い持ち味、書き味が欲しい&lt;/li&gt;&lt;li&gt;細くてよく滑るペン先が何より欲しい！&lt;/li&gt;&lt;li&gt;値段は高くても気にしない&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight:bold;"&gt;パワーサポート スマートペン&lt;/span&gt; をオススメする人&lt;ul&gt;&lt;li&gt;軽くて、書いていて疲れないペンが欲しい&lt;/li&gt;&lt;li&gt;感度の良くて、実際のペンみたいに少し抵抗がある滑りのペン先が何より欲しい！&lt;/li&gt;&lt;li&gt;値段は安い方がいい、または初めてスタイラスを試してみるので失敗しても後悔しない値段の方がいい&lt;/li&gt;&lt;/ul&gt;私自身はどっちを選ぼうか悩んでますが、せっかく買ったし、しばらくはBamboo Stylusを使ってみようかと考えてます。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-7953543331835974705?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/7953543331835974705/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=7953543331835974705' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/7953543331835974705'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/7953543331835974705'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/05/ipad-bamboo-stylus.html' title='iPad 用スタイラス Bamboo Stylus を試してみた'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-2XUXIo93S2w/TeHwH9Oyg8I/AAAAAAAACmE/9q6_l3siGvE/s72-c/bamboo_stylus.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-2809230529568723402</id><published>2011-05-29T12:09:00.005+09:00</published><updated>2011-05-29T12:40:37.339+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Xcode 4.0.2'/><category scheme='http://www.blogger.com/atom/ns#' term='ビルド'/><category scheme='http://www.blogger.com/atom/ns#' term='Xcode'/><category scheme='http://www.blogger.com/atom/ns#' term='Objective-C'/><title type='text'>-ObjC とか -all_load って何をやってるのか調べてみた</title><content type='html'>よく外部のライブラリやFrameworkをiOSのプロジェクトに取り込むときに、つけないと動かないからつけてねと言われる、 Other Linker Flag = -ObjC -all_load のフラグ。これって何をやっているのか今までずっと気になっていたので、ちょっと調べてみました。&lt;br /&gt;&lt;br /&gt;こういうことらしいです。&lt;br /&gt;&lt;a href="http://developer.apple.com/library/mac/#qa/qa1490/_index.html"&gt;http://developer.apple.com/library/mac/#qa/qa1490/_index.html&lt;/a&gt;&lt;br /&gt;&lt;blockquote&gt;This flag causes the linker to load every object file in the library that defines an Objective-C class or category. While this option will typically result in a larger executable (due to additional object code loaded into the application), it will allow the successful creation of effective Objective-C static libraries that contain categories on existing classes.&lt;/blockquote&gt;&lt;blockquote&gt;このフラグは、Objective-Cのクラスまたはカテゴリを定義しているライブラリに含まれる、全てのオブジェクトファイルをロードするようリンカに促します。これによってたいていの場合実行ファイルのサイズが大きくなってしまいますが（アプリに追加のオブジェクトコードが読み込まれるので）、既存のクラスに対するカテゴリを含むObjective-C静的ライブラリを正しく使えるようになります。&lt;/blockquote&gt;へぇぇ！全く知らなかったです。ちなみに -all_load はというと、&lt;blockquote&gt;-all_load forces the linker to load all object files from every archive it sees, even those without Objective-C code. -force_load is available in Xcode 3.2 and later. It allows finer grain control of archive loading. Each -force_load option must be followed by a path to an archive, and every object file in that archive will be loaded.&lt;/blockquote&gt;&lt;blockquote&gt;-all_load は全てのオブジェクトファイルを全ての認識できる静的ライブラリ（アーカイブ）から全部ロードしてくる（意訳）&lt;/blockquote&gt;とかそういうことらしいです。なるほどねー。&lt;br /&gt;&lt;br /&gt;ということは -all_load はより強力な -ObjC に見えますが、実際には -ObjC は -all_load と違って上記に記載されているオブジェクトファイルのロードの挙動変化以外にも何かやっているようで、実際 -all_load -ObjC 両方指定してあるとリンクできるのに、 -all_load だけではリンクが通らない場合がありました。なのでやっぱり必要なときはまず -ObjC だけを試してみて、それでも駄目なら両方設定するのがいいみたいですね。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;余談ですが、上記の内容を調べていたとき、リンカとかローダについて詳しく学ぶには以下の本がよいとオススメしていただきました。&lt;br /&gt;&lt;br /&gt;Linkers and Loaders (日本語訳版もありますが、訳がひどいので英語版の方がよいとのことです。ここでは日本語版のリンクはあえて紹介しません)&lt;br /&gt;&lt;a href="http://linker.iecc.com/"&gt;http://linker.iecc.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;table  border="0" cellpadding="5"&gt;&lt;tr&gt;&lt;td valign="top"&gt;&lt;a href="http://www.amazon.co.jp/%E3%83%AA%E3%83%B3%E3%82%AB%E3%83%BB%E3%83%AD%E3%83%BC%E3%83%80%E5%AE%9F%E8%B7%B5%E9%96%8B%E7%99%BA%E3%83%86%E3%82%AF%E3%83%8B%E3%83%83%E3%82%AF%E2%80%95%E5%AE%9F%E8%A1%8C%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AB%E5%BF%85%E9%A0%88%E3%81%AE%E6%8A%80%E8%A1%93-COMPUTER-TECHNOLOGY-%E5%9D%82%E4%BA%95-%E5%BC%98%E4%BA%AE/dp/4789838072%3FSubscriptionId%3D15SMZCTB9V8NGR2TW082%26tag%3Dakisutesama-22%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D4789838072" target="_blank"&gt;&lt;img src="http://ecx.images-amazon.com/images/I/51AySwK0kiL._SL160_.jpg" border="0" alt="4789838072" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;font size="-1"&gt;&lt;a href="http://www.amazon.co.jp/%E3%83%AA%E3%83%B3%E3%82%AB%E3%83%BB%E3%83%AD%E3%83%BC%E3%83%80%E5%AE%9F%E8%B7%B5%E9%96%8B%E7%99%BA%E3%83%86%E3%82%AF%E3%83%8B%E3%83%83%E3%82%AF%E2%80%95%E5%AE%9F%E8%A1%8C%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AB%E5%BF%85%E9%A0%88%E3%81%AE%E6%8A%80%E8%A1%93-COMPUTER-TECHNOLOGY-%E5%9D%82%E4%BA%95-%E5%BC%98%E4%BA%AE/dp/4789838072%3FSubscriptionId%3D15SMZCTB9V8NGR2TW082%26tag%3Dakisutesama-22%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D4789838072" target="_blank"&gt;リンカ・ローダ実践開発テクニック―実行ファイルを作成するために必須の技術 (COMPUTER TECHNOLOGY)&lt;/a&gt;&lt;img src="http://www.assoc-amazon.jp/e/ir?t=akisutesama-22&amp;l=ur2&amp;o=9" width="1" height="1" style="border: none;" alt="" /&gt;&lt;br /&gt;坂井 弘亮 &lt;br /&gt;CQ出版  2010-08&lt;br /&gt;&lt;br /&gt;&lt;/font&gt;&lt;font size="-2"&gt;by &lt;a href="http://www.goodpic.com/mt/aws/index.html" &gt;G-Tools&lt;/a&gt;&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;KindleかiBooksで欲しかったのですが、残念ながら紙の本しかないですね・・・＞＜&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-2809230529568723402?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/2809230529568723402/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=2809230529568723402' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/2809230529568723402'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/2809230529568723402'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/05/objc-allload.html' title='-ObjC とか -all_load って何をやってるのか調べてみた'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-7749808966967369262</id><published>2011-05-05T13:32:00.002+09:00</published><updated>2011-05-05T13:34:10.569+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Xcode 4.0.2'/><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='Xcode'/><category scheme='http://www.blogger.com/atom/ns#' term='コマンドライン'/><title type='text'>atos を使ってアプリのクラッシュログを symbolicate する方法</title><content type='html'>iOSアプリがクラッシュするとクラッシュログがデバイスに残され、 Xcode のオーガナイザーからログを取得してバグの原因を解析できるのは皆さんご存知の通りだと思います。このとき、基本的には Xcode がクラッシュログがの中のシンボルを自動的に読める状態にしてくれる (symbolicate) のですが、どうも Xcode 4 になってからこの symbolicate がいまいちよく動いてくれないので、手動で symbolicate をする方法を調べてみました。&lt;br /&gt;&lt;br /&gt;参考にしたページは以下の通り。&lt;br /&gt;&lt;a href="http://stackoverflow.com/questions/1460892/symbolicating-iphone-app-crash-reports"&gt;http://stackoverflow.com/questions/1460892/symbolicating-iphone-app-crash-reports&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■atosの使い方&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;symbolicate をするには Xcode に付属している atos というコマンドラインツールと、ビルドの際に生成される dSYM と呼ばれるファイルを使います。&lt;br /&gt;&lt;br /&gt;まずは dSYM ファイルを探します。 Xcode 4 の場合は、デフォルトで *~/Library/Developer/Xcode/DerivedData/プロジェクト名-ランダムな文字列/Build/Products/ビルド設定名/アプリ名.app.dSYM* に生成されるようになっているはずです。&lt;br /&gt;&lt;br /&gt;dSYM ファイルが見つかったら、コンソールから atos を実行します。 atos の使い方は以下のとおりです。&lt;pre&gt;atos -arch アプリがクラッシュしたデバイスのアーキテクチャ -o アプリ名.app.dSYM/Contents/Resources/DWARF/アプリ名 クラッシュした関数またはメソッドのアドレス&lt;/pre&gt;実際にやってみるとこんな感じです。&lt;pre&gt;cd ~/Library/Developer/Xcode/DerivedData/MyProject-xxxxxxxxxxxxxxxxxxxxxxxxxxxx/Build/Products/Debug-iphoneos/&lt;br /&gt;atos -arch armv7 -o MyApp.app.dSYM/Contents/Resources/DWARF/MyApp 0x00072ce6&lt;/pre&gt;これで指定されたアドレスが symbolicate され、シンボル名および元のソースコード上の行数まで表示してくれます。超便利です。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■注意点&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;何回か試してみましたが、ときどき実際にクラッシュしたシンボルと違うシンボルが表示されることがあるみたいです。上記で紹介したやり方が間違っているのか、それともそういうものなのかわからないのですが・・・すんません＞＜ しかしその場合でもだいたい表示されたシンボルの近くが問題の原因だったため、いまのところ参考ぐらいには使えています。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-7749808966967369262?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/7749808966967369262/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=7749808966967369262' title='1 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/7749808966967369262'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/7749808966967369262'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/05/atos-symbolicate.html' title='atos を使ってアプリのクラッシュログを symbolicate する方法'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-7887847916964048049</id><published>2011-05-03T10:57:00.004+09:00</published><updated>2011-05-03T11:06:52.260+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Xcode 4.0.2'/><category scheme='http://www.blogger.com/atom/ns#' term='ビルド'/><category scheme='http://www.blogger.com/atom/ns#' term='Xcode'/><category scheme='http://www.blogger.com/atom/ns#' term='設定'/><title type='text'>Xcode のビルド設定で $(inherited) を使って設定を継承する</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-htseOMHuUh0/Tb9hIEJhYYI/AAAAAAAACl8/5ej2PZmpiaI/s1600/usingdollerinherited.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 207px;" src="http://3.bp.blogspot.com/-htseOMHuUh0/Tb9hIEJhYYI/AAAAAAAACl8/5ej2PZmpiaI/s400/usingdollerinherited.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5602303252652712322" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Appleの&lt;a href="http://developer.apple.com/tools/xcode/xcodebuildsettings.html"&gt;Xcode 2のころのドキュメント&lt;/a&gt;によるとXcodeのビルド設定は以下の順に設定内容が解決されていきます。&lt;ol&gt;&lt;li&gt;ユーザーのデフォルトの環境変数設定（たいていは ~/.MacOSX/environment.plist で指定されている）&lt;/li&gt;&lt;li&gt;Xcodeのビルトインデフォルト設定&lt;/li&gt;&lt;li&gt;Xcodeのアプリケーション設定（これはXcode 4では廃止されている気がします）&lt;/li&gt;&lt;li&gt;ベースとなるビルド設定ファイル（元のドキュメントには書いてありませんが、.xcconfigファイルを使ってビルド設定を指定可能です）&lt;/li&gt;&lt;li&gt;プロジェクトのビルド設定&lt;/li&gt;&lt;li&gt;ターゲットのビルド設定&lt;/li&gt;&lt;li&gt;コマンドラインから起動した場合は、コマンドラインのビルド設定フラグの値&lt;/li&gt;&lt;/ol&gt;このとき、下位の設定は上位の設定を上書きして使用するようになっているのですが、ここで上位の設定をそのまま受け継いで使いたい場合には、設定項目に&lt;code&gt;$(inherited)&lt;/code&gt;という特殊な値を指定することが可能です。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-7887847916964048049?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/7887847916964048049/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=7887847916964048049' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/7887847916964048049'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/7887847916964048049'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/05/xcode-inherited.html' title='Xcode のビルド設定で $(inherited) を使って設定を継承する'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-htseOMHuUh0/Tb9hIEJhYYI/AAAAAAAACl8/5ej2PZmpiaI/s72-c/usingdollerinherited.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-2062834096824132139</id><published>2011-04-23T15:01:00.003+09:00</published><updated>2011-04-23T15:25:27.697+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Keychain'/><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='Objective-C'/><category scheme='http://www.blogger.com/atom/ns#' term='iOS 4.3.2'/><category scheme='http://www.blogger.com/atom/ns#' term='Cocoa'/><title type='text'>KeychainItemWrapper を改造して、複数の Keychain Item に同時にアクセス出来るようにしてみた</title><content type='html'>※2011/04/23現在での情報です。以下の問題は全て Apple に対して報告いたしましたので、ひょっとしたら将来的に修正されるかもしれません。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;現在の仕事にて課金情報を安全にアプリケーション内に保存したいということになり、それならばということで iOS に最初から用意されている Security.framework を使って Keychain 領域に情報を保存するアプリを作ることにしました。この Security.framework は全てC言語にて実装されており、そのまま使うと非常に取っつきづらいです。そこで、 Apple がサンプルコードとして提供している &lt;a href="http://developer.apple.com/library/ios/#samplecode/GenericKeychain/Introduction/Intro.html"&gt;GenericKeychain プロジェクト&lt;/a&gt;の &lt;a href="http://developer.apple.com/library/ios/#samplecode/GenericKeychain/Listings/Classes_KeychainItemWrapper_h.html"&gt;KeychainItemWrapper クラス&lt;/a&gt;を使って Keychain 領域にアクセスすることにしました。&lt;br /&gt;&lt;br /&gt;最初は問題ないように見えたのですが、実はこの KeychainItemWrapper クラス、Version 1.2には深刻なバグがあります。それは、&lt;span style="font-weight:bold; color:#cc0000;"&gt;複数の KeychainItemWrapper クラスのインスタンスを使って複数の識別子を持った情報を保存しようとすると、同時に一種類しか保存できなくなる&lt;/span&gt;（二つめを保存しようとするとステータスコード25299が返却されて保存できなくなる）というものです。&lt;br /&gt;&lt;br /&gt;原因を調査した結果、以下のページに記載されている内容が問題だとわかりました。&lt;br /&gt;&lt;a href="http://useyourloaf.com/blog/2010/3/29/simple-iphone-keychain-access.html"&gt;http://useyourloaf.com/blog/2010/3/29/simple-iphone-keychain-access.html&lt;/a&gt;&lt;blockquote&gt;The combination of the final two attributes kSecAttrAccount and kSecAttrService should be set to something unique for this keychain. In this example I set the service name to a static string and reuse the identifier as the account name.&lt;/blockquote&gt;サンプルで提供されている KeychainItemWrapper クラスにはこれらの一意となるキーが指定されておらず、単に検索用の kSecAttrGeneric だけが指定されていたため、一意キーの指定がおかしくなって二つ目の Keychain アイテムが保存できなくなっていた、というわけです。&lt;br /&gt;&lt;br /&gt;そこでこちらの問題を修正した KeychainItemWrapper クラスをご用意しました。&lt;br /&gt;&lt;a href="https://gist.github.com/938375"&gt;https://gist.github.com/938375&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;ライセンスは元となるAppleのオープンソースライセンスに準拠します。改変・再配布・利用すべて自由ですが、その際ソースコードの最上部にあるAppleのライセンス条項コードは絶対に改変しないでください。Apple先生に何か言われても私は知りませんよ＞＜&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■修正版 KeychainItemWrapper の使い方&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;基本的には通常の KeychainItemWrapper と何ら変わりません。&lt;pre class="prettyprint linenums"&gt;// インスタンスを作る&lt;br /&gt;KeychainItemWrapper *wrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"com.akisute.keychain.KeychainTestApp.item1"&lt;br /&gt;                                                                   serviceName:@"com.akisute.KeychainTestApp"&lt;br /&gt;                                                                   accessGroup:nil];&lt;br /&gt;&lt;br /&gt;// 値を保存する&lt;br /&gt;// いったんresetKeychainItemしているのはmyValueがnilのとき保存されているデータを削除したいから&lt;br /&gt;// 基本的に値(kSecValueData)として保存できるのはUTF-8のNSStringのみです。内部的にNSDataに変換されてKeychainに保存されます。&lt;br /&gt;// それ以外の情報を保存したい場合はすみませんが未対応です＞＜ Base64文字列にするとかJSON文字列にするとか工夫して回避してください＞＜&lt;br /&gt; NSString *myValue = @"abesi";&lt;br /&gt;[wrapper resetKeychainItem];&lt;br /&gt;[wrapper setObject:myValue forKey:(id)kSecValueData];&lt;br /&gt;&lt;br /&gt;// 値を取り出す&lt;br /&gt;NSString *resultValue = [wrapper objectForKey:(id)kSecValueData];&lt;br /&gt;NSLog(@"resultvalue = %@", resultValue);&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-2062834096824132139?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/2062834096824132139/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=2062834096824132139' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/2062834096824132139'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/2062834096824132139'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/04/keychainitemwrapper-keychain-item.html' title='KeychainItemWrapper を改造して、複数の Keychain Item に同時にアクセス出来るようにしてみた'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-3117714058224959567</id><published>2011-04-23T13:40:00.006+09:00</published><updated>2011-05-02T14:17:13.778+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iOS 3.1.3'/><category scheme='http://www.blogger.com/atom/ns#' term='バグ'/><category scheme='http://www.blogger.com/atom/ns#' term='UI'/><title type='text'>iOS 3の UIScrollView はスクロールが発生しない状態では内部の UIView のタッチが取れない</title><content type='html'>iOS 3以前と iOS 4以降で大きく内部実装が変わったクラスがいくつかあります。 UIScrollView はその中の一つですが、ここではその中でもかなり厄介なバグを紹介します。&lt;br /&gt;&lt;br /&gt;iOS 3の UIScrollView は、スクロールが発生しない状態（すなわち UIScrollView.bounds.size &gt;= UIScrollView.contentSize のとき）では内部の UIView のタッチが取れません。タッチが取れないというのは、要するに内部の UIView に実装してある touchesBegan, touchesMoved, touchesEnded などが呼び出されないということです。情報元はこちら。&lt;br /&gt;&lt;a href="http://www.iphonedevsdk.com/forum/iphone-sdk-development/1345-uiscrollview-subview-touch-problem.html"&gt;http://www.iphonedevsdk.com/forum/iphone-sdk-development/1345-uiscrollview-subview-touch-problem.html&lt;/a&gt;&lt;blockquote&gt;Looks like as if the scrollview blocks any touches when the content rectangle is smaller or of same size as its bounds. Really strange behaviour. &lt;/blockquote&gt;ほんと Really strange behavior ですよ Apple センセ。&lt;br /&gt;&lt;br /&gt;回避策として、iOS 3では UIScrollView.contentSize を調整して、常にスクロールが発生するような状態にしておけば大丈夫です。 iOS 4以降でしたらこの問題は発生しません。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;2011/05/02追記: &lt;a href="http://twitter.com/k_katsumi/"&gt;@k_katsumi&lt;/a&gt; さんから突っ込みいただきました。&lt;br /&gt;&lt;a href="http://twitter.com/#!/k_katsumi/status/61690186664378368"&gt;http://twitter.com/#!/k_katsumi/status/61690186664378368&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;以下のように delaysContentTouches プロパティと canCancelContentTouches プロパティを NO に設定する方がどうもお行儀がよいようです。&lt;pre class="prettyprint linenums"&gt;scrollView.delaysContentTouches = NO;&lt;br /&gt;scrollView.canCancelContentTouches = NO;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-3117714058224959567?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/3117714058224959567/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=3117714058224959567' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/3117714058224959567'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/3117714058224959567'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/04/ios-3-uiscrollview-uiview.html' title='iOS 3の UIScrollView はスクロールが発生しない状態では内部の UIView のタッチが取れない'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-5835441771197628321</id><published>2011-04-23T13:23:00.003+09:00</published><updated>2011-04-23T13:31:58.357+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iOS 3.2'/><category scheme='http://www.blogger.com/atom/ns#' term='iOS 4.3.2'/><category scheme='http://www.blogger.com/atom/ns#' term='UI'/><title type='text'>UIButton でアニメーションする画像を表示させたい</title><content type='html'>UIButton でアニメーションする画像を表示させたいときは、 UIButton.imageView.animationImages プロパティを使うことで簡単にアニメーションを実装させることができます。さっそくサンプルを書いてみます。&lt;br /&gt;&lt;br /&gt;以下、 iOS 3.2 および iOS 4.0 以降にて確認しております。&lt;pre class="prettyprint linenums"&gt;UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];&lt;br /&gt;&lt;br /&gt;NSArray *animationImageNames = [NSArray arrayWithObjects:@"animation1.png", @"animation2.png", @"animation3.png", nil];&lt;br /&gt;NSMutableArray *animationImages = [NSMutableArray arrayWithCapacity:[animationImageNames count]];&lt;br /&gt;&lt;br /&gt;for (NSString *animationImageName in animationImageNames) {&lt;br /&gt;    UIImage *image = [UIImage imageNamed:animationImageName];&lt;br /&gt;    [animationImages addObject:image];&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;[button setImage:[animationImages objectAtIndex:0] forState:UIControlStateNormal]; // 大事&lt;br /&gt;button.imageView.animationImages = animationImages;&lt;br /&gt;button.imageView.animationDuration = 2.0;&lt;br /&gt;[button.imageView startAnimating]; // 大事、忘れるとアニメーションしません&lt;br /&gt;&lt;br /&gt;[self.view addSubview:button];&lt;/pre&gt;UIButton.imageView.animationImages プロパティを使う際に注意する点がいくつかあります。&lt;ul&gt;&lt;li&gt;必ず最初に setImage:forState: メソッドを使って何らかの画像を表示させるようにすること。通常の画像を表示させるようにしないと、 UIButton.imageView が画面に表示されません。&lt;/li&gt;&lt;li&gt;iOS 4.0以降ではこのプロパティでセットした画像は UIButton の frame に合わせてリサイズされて表示されますが、 iOS 3.2 以前ではリサイズされずそのままの大きさで表示されますので、注意が必要です。&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/42067579805640535-5835441771197628321?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/5835441771197628321/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=5835441771197628321' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/5835441771197628321'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/5835441771197628321'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/04/uibutton.html' title='UIButton でアニメーションする画像を表示させたい'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-4158337577633699722</id><published>2011-04-17T14:39:00.003+09:00</published><updated>2011-04-17T14:49:28.342+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Xcode 4.0.2'/><category scheme='http://www.blogger.com/atom/ns#' term='バグ'/><category scheme='http://www.blogger.com/atom/ns#' term='Xcode 4.0.1'/><category scheme='http://www.blogger.com/atom/ns#' term='Xcode'/><category scheme='http://www.blogger.com/atom/ns#' term='設定'/><category scheme='http://www.blogger.com/atom/ns#' term='Xcode 4.0'/><title type='text'>Xcode 4 で scheme が My Mac 64bit になって iPhone 向けのビルドが出来なくなった時の対処法</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-unkTp1kX4Zk/Tap_YnuWYfI/AAAAAAAACl0/-bx1-2F-Wks/s1600/howtodealwithmymac64biterrorinxcode4.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 77px;" src="http://1.bp.blogspot.com/-unkTp1kX4Zk/Tap_YnuWYfI/AAAAAAAACl0/-bx1-2F-Wks/s400/howtodealwithmymac64biterrorinxcode4.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5596425547918238194" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;最近会社のプロジェクトで使う Xcode を Xcode 4 に乗り換えたのですが、全く新しく作り直された &lt;del&gt;バグだらけでまともにビルドすら出来ない上に無料じゃなくなったどうしようもない出来映えの&lt;/del&gt; IDE ということで、何かとトラブルが多いようです。今回はその中でももっとも頻発したものをご紹介します。&lt;br /&gt;&lt;br /&gt;たまに iOS 向けのプロジェクトを Xcode 4 で開いたときに、左上の scheme 選択欄に My Mac 64bit と表示されてしまって iPhone シミュレータや実機でビルドが出来なくなることがあるようです。&lt;br /&gt;&lt;br /&gt;対処法はこちら。&lt;br /&gt;&lt;a href="http://stackoverflow.com/questions/5319251/xcode-4-the-selected-run-destination-is-not-valid-for-this-action"&gt;http://stackoverflow.com/questions/5319251/xcode-4-the-selected-run-destination-is-not-valid-for-this-action&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Build Settings を開き、 Base SDK の設定をいったん Mac OS X SDK に変更してから、もとの iOS SDK に戻すと問題が解決されるようです。これで一安心ですね。&lt;br /&gt;&lt;br /&gt;Xcode 4.0 と Xcode 4.0.1 で再現することを確認しました。 Xcode 4.0.2 では未確認です。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-4158337577633699722?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/4158337577633699722/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=4158337577633699722' title='4 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/4158337577633699722'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/4158337577633699722'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/04/xcode-4-scheme-my-mac-64bit-iphone.html' title='Xcode 4 で scheme が My Mac 64bit になって iPhone 向けのビルドが出来なくなった時の対処法'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-unkTp1kX4Zk/Tap_YnuWYfI/AAAAAAAACl0/-bx1-2F-Wks/s72-c/howtodealwithmymac64biterrorinxcode4.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-2192289283343887936</id><published>2011-04-17T14:22:00.004+09:00</published><updated>2011-04-17T14:27:55.388+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='バグ'/><category scheme='http://www.blogger.com/atom/ns#' term='Xcode'/><category scheme='http://www.blogger.com/atom/ns#' term='設定'/><category scheme='http://www.blogger.com/atom/ns#' term='Xcode 4.0'/><title type='text'>Xcode 4 で build target 名にスペースが含まれているとビルド時に 100% エラーになる</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-w9f7V5RYxUY/Tap5qQ6RDhI/AAAAAAAACls/vN28BxLzLBY/s1600/BuildTarget%25E5%2590%258D%25E3%2581%25AB%25E3%2582%25B9%25E3%2583%259A%25E3%2583%25BC%25E3%2582%25B9%25E3%2581%258C%25E3%2581%2582%25E3%2582%258B%25E3%2581%25A8%25E3%2583%2580%25E3%2583%25A12.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 197px;" src="http://3.bp.blogspot.com/-w9f7V5RYxUY/Tap5qQ6RDhI/AAAAAAAACls/vN28BxLzLBY/s400/BuildTarget%25E5%2590%258D%25E3%2581%25AB%25E3%2582%25B9%25E3%2583%259A%25E3%2583%25BC%25E3%2582%25B9%25E3%2581%258C%25E3%2581%2582%25E3%2582%258B%25E3%2581%25A8%25E3%2583%2580%25E3%2583%25A12.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5596419253962083858" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;タイトルからしてひどい出落ちですが、 Xcode 4 で build target 名にスペースが含まれているとビルドを行った際に 100% ビルドに失敗します。&lt;br /&gt;&lt;br /&gt;原因がまたお粗末で、 Xcode 4 は build target 名をビルド成果物の中間配置ディレクトリの名前に使っているのですが、スペースをエスケープしていないためコンパイラが正しくパスを解釈できずに落ちているようです。がっくし。&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-fTG0VBdRwTI/Tap5qPv01cI/AAAAAAAAClk/v0djxmma1Hs/s1600/BuildTarget%25E5%2590%258D%25E3%2581%25AB%25E3%2582%25B9%25E3%2583%259A%25E3%2583%25BC%25E3%2582%25B9%25E3%2581%258C%25E3%2581%2582%25E3%2582%258B%25E3%2581%25A8%25E3%2583%2580%25E3%2583%25A1.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 116px;" src="http://1.bp.blogspot.com/-fTG0VBdRwTI/Tap5qPv01cI/AAAAAAAAClk/v0djxmma1Hs/s400/BuildTarget%25E5%2590%258D%25E3%2581%25AB%25E3%2582%25B9%25E3%2583%259A%25E3%2583%25BC%25E3%2582%25B9%25E3%2581%258C%25E3%2581%2582%25E3%2582%258B%25E3%2581%25A8%25E3%2583%2580%25E3%2583%25A1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5596419253649855938" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Xcode 4.0 での調査結果です。 4.0.1 または 4.0.2 では修正されている可能性がありますが、いずれにせよスペースはさけたほうが良さそうです。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-2192289283343887936?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/2192289283343887936/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=2192289283343887936' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/2192289283343887936'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/2192289283343887936'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/04/xcode-4-build-target-100.html' title='Xcode 4 で build target 名にスペースが含まれているとビルド時に 100% エラーになる'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-w9f7V5RYxUY/Tap5qQ6RDhI/AAAAAAAACls/vN28BxLzLBY/s72-c/BuildTarget%25E5%2590%258D%25E3%2581%25AB%25E3%2582%25B9%25E3%2583%259A%25E3%2583%25BC%25E3%2582%25B9%25E3%2581%258C%25E3%2581%2582%25E3%2582%258B%25E3%2581%25A8%25E3%2583%2580%25E3%2583%25A12.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-8017446842840879557</id><published>2011-04-17T13:46:00.005+09:00</published><updated>2011-04-17T14:14:46.312+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iOS 4.3.1'/><category scheme='http://www.blogger.com/atom/ns#' term='Cocoa'/><category scheme='http://www.blogger.com/atom/ns#' term='UI'/><title type='text'>UINavigationController に管理されている UIViewController の view のサイズを変更したい</title><content type='html'>たとえばアプリ内の固定の位置に広告を突っ込みたいときなど、 UINavigationController に管理されている UIViewController の view 構造を操作したい場合があると思いますので、調べてみました。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■UINavigationController.viewの中身&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;iOS 4 ですと以下のようになっています。&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-u_qQ-fwf5gA/Tap2lkMYwVI/AAAAAAAAClc/w2IcLN3OwAg/s1600/uinavigationcontrollerviewrecursivedescription.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 123px;" src="http://3.bp.blogspot.com/-u_qQ-fwf5gA/Tap2lkMYwVI/AAAAAAAAClc/w2IcLN3OwAg/s400/uinavigationcontrollerviewrecursivedescription.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5596415874704130386" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;最上位の UINavigationController.view に相当するのが UILayoutContainerView で、その下に UINavigationTransitionView があり、そのまた下に UIViewControllerWrapperView というのがあって、こいつが表示される UIViewController.view をラップして表示しているという仕組みになっているようです。&lt;br /&gt;&lt;br /&gt;おそらく iOS 3.2 でも同じだと思います。 iOS 3.1.3 以前についてはわかりません。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■実際にやってみる&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;いろいろ試してみた結果、もっともうまくいきそうなのは以下のように、 viewDidAppear のタイミングで UIViewController.view.superview に対して操作を行う方法であることがわかりました。&lt;pre class="prettyprint linenums"&gt;- (void)viewDidAppear:(BOOL)animated&lt;br /&gt;{&lt;br /&gt;    [super viewDidAppear:animated];&lt;br /&gt;    self.headerView.frame = CGRectMake(0, 0, 320, 100);&lt;br /&gt;    self.view.frame = CGRectMake(0, 100, 320, self.view.superview.frame.size.height - 100);&lt;br /&gt;    [self.view.superview addSubview:self.headerView];&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■問題発生&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;ところがこの方法では画面遷移時のアニメーションが発生すると上記の例で追加した headerView の表示が無茶苦茶に壊れてしまいます。またタイミングを誤ると headerView のサイズが self.view.superview.bounds の大きさに補正されてしまいます。恐らくは UINavigationTransitionView とかいう private な view がなにやらやっているのでしょう。アニメーションが発生しない範囲であれば問題なさそうですが、いまいちです。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■結論&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;横着しないで表示される UIViewController の view で何とかするしかないみたいですね＞＜&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-8017446842840879557?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/8017446842840879557/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=8017446842840879557' title='2 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/8017446842840879557'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/8017446842840879557'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/04/uinavigationcontroller-uiviewcontroller.html' title='UINavigationController に管理されている UIViewController の view のサイズを変更したい'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-u_qQ-fwf5gA/Tap2lkMYwVI/AAAAAAAAClc/w2IcLN3OwAg/s72-c/uinavigationcontrollerviewrecursivedescription.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-7801692172305640387</id><published>2011-03-17T18:58:00.003+09:00</published><updated>2011-04-03T10:37:57.188+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ビルド'/><category scheme='http://www.blogger.com/atom/ns#' term='Xcode'/><category scheme='http://www.blogger.com/atom/ns#' term='Xcode 4.0'/><category scheme='http://www.blogger.com/atom/ns#' term='Three20'/><title type='text'>Xcode 4 で昔の Three20 フレームワークを使っているプロジェクトをビルドする方法</title><content type='html'>主に自分用のメモ。&lt;br /&gt;Xcode 3 時代に作った Three20 フレームワークを使っているプロジェクトが動かない場合の対処法です。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;動かない原因は簡単で、Xcode 4からはビルドした生成物が用意される場所が、各プロジェクトのbuildディレクトリ以下から、&lt;pre&gt;~/Library/Developer/Xcode/DerivedData/プロジェクト名/Build/Products&lt;/pre&gt;以下に移動しているからです。なので、たいていの場合ヘッダ検索パスが間違っているので動かなくなります。&lt;br /&gt;&lt;br /&gt;対処法はThree20公式ブログに載っているので転載します。&lt;br /&gt;&lt;a href="http://three20.info/article/2011-03-10-Xcode4-Support"&gt;http://three20.info/article/2011-03-10-Xcode4-Support&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;以下のようにヘッダ検索パスを追記すると良いようです。&lt;pre&gt;"$(BUILT_PRODUCTS_DIR)/../three20"&lt;br /&gt;"$(BUILT_PRODUCTS_DIR)/../../three20"&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;2011/04/03追記: はじめに載せていた対処法は間違いでしたorz&lt;/span&gt; 大変申し訳ありません！&lt;br /&gt;以下、はじめに掲載していた間違っている対処法です。この方法では通常のビルドはうまくいきますが、アーカイブ時のビルドに失敗します！どうもアーカイブ時と通常のビルド時でもビルド先のディレクトリが指し示す先が異なるようです、&lt;br /&gt;&lt;br /&gt;対処法は、以下のようにヘッダ検索パスを書き直します。&lt;pre&gt;$SYMROOT/three20&lt;/pre&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-Rd3YAluN9Ck/TYHcintjmgI/AAAAAAAAClU/wvtdh1KFKRM/s1600/headersearchpathswithsymroot.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 166px;" src="http://1.bp.blogspot.com/-Rd3YAluN9Ck/TYHcintjmgI/AAAAAAAAClU/wvtdh1KFKRM/s400/headersearchpathswithsymroot.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5584987500249848322" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;$SYMROOTという環境変数がキモです。&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-X949CIGVesU/TYHciYx7ayI/AAAAAAAAClM/5jq6i_EK1Lg/s1600/symroot.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 289px;" src="http://4.bp.blogspot.com/-X949CIGVesU/TYHciYx7ayI/AAAAAAAAClM/5jq6i_EK1Lg/s400/symroot.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5584987496241654562" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;こいつはドキュメントには書いてませんが、Xcode 4のビルド設定ですと、&lt;pre&gt;~/Library/Developer/Xcode/DerivedData/プロジェクト名/Build/Products&lt;/pre&gt;に対応するパスを返してくれるようです。&lt;br /&gt;&lt;br /&gt;2011/04/03追記: 上にも書きましたが、アーカイブ時には上記に対応するパスではなく、異なるパスが使われます。そのためこの方法ではうまくいきません。Three20.infoに掲載されている方法を使うのが一番良いようです。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-7801692172305640387?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/7801692172305640387/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=7801692172305640387' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/7801692172305640387'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/7801692172305640387'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/03/xcode-4-three20.html' title='Xcode 4 で昔の Three20 フレームワークを使っているプロジェクトをビルドする方法'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-Rd3YAluN9Ck/TYHcintjmgI/AAAAAAAAClU/wvtdh1KFKRM/s72-c/headersearchpathswithsymroot.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-5748448958686634856</id><published>2011-03-16T21:29:00.004+09:00</published><updated>2011-03-16T22:05:58.751+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Xcode 3.2.6'/><category scheme='http://www.blogger.com/atom/ns#' term='Python 2.6.1'/><category scheme='http://www.blogger.com/atom/ns#' term='ビルド'/><category scheme='http://www.blogger.com/atom/ns#' term='Xcode'/><category scheme='http://www.blogger.com/atom/ns#' term='Xcode 4.0'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Python で Xcode のビルドスクリプトを書く方法</title><content type='html'>以前&lt;a href="http://akisute.com/2011/01/python-5-xml.html"&gt;こんな記事&lt;/a&gt;を書きましたが、今回はもっと実践的なお話。PythonでXcodeのビルドスクリプトを書いてハッピーになろうというお話です。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■なぜXcodeのビルドスクリプトを書くのか&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Xcodeのビルド機能だけでは出来ないことをやりたいからです。たとえば、&lt;ul&gt;&lt;li&gt;特定のディレクトリの中に入っているリソースを、ビルド時にアプリにパッケージングしたい。&lt;/li&gt;&lt;li&gt;ビルドする前に、特定のリソースを暗号化して、アプリにパッケージングしたい。&lt;/li&gt;&lt;/ul&gt;といった要望が結構ありますが、これらはビルドスクリプトを使えば簡単に可能になります。&lt;br /&gt;手でいちいちやるより楽で安全ですね。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■なぜPythonか&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;理由はいくつかあります。&lt;ol&gt;&lt;li&gt;Windows, Mac, Linux, 全ての環境で動く。したがって、万が一のときにはビルドスクリプトだけを移植できる。&lt;/li&gt;&lt;li&gt;sh とか csh とか非力すぎてやってらんない。 zsh もつかえるけど Python よりはやはり弱いと思う。&lt;/li&gt;&lt;li&gt;スクリプトを Xcode 内部のエディタで書いて、そこに閉じ込められてしまうため、可搬性が無くなってしまう。&lt;/li&gt;&lt;li&gt;外部スクリプトにしておくと、引数としてオプションを渡せるので、ビルド設定に応じてオプションを切り替えたり、テストと本番でオプションを切り替えて動作を変更する、とかできる&lt;/li&gt;&lt;/ol&gt;たとえばクライアント・サーバーアプリで、サーバー側がPythonで出来ていたりする場合、&lt;br /&gt;サーバー側の処理を一部ビルド時にやりたいとかあったりするわけですよ。・・・たまに。・・・ごくまれに。&lt;br /&gt;そういうときに便利です。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■例:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;長々と語るより例を示した方がよいと思うので、さっそくビルドスクリプトの例を示します。&lt;br /&gt;ここでご紹介するのは、プロジェクトの/Resources/MyResourceディレクトリ以下にあるファイルを全てアプリバンドル内の/MyResourcesディレクトリ以下にコピーするだけの簡単なビルドスクリプトです。オプションとして平文/暗号化の有無を選択できるようにしてみました（実装はしてないです＞＜）&lt;br /&gt;&lt;br /&gt;Xcodeがビルドスクリプトを実行する際に、環境変数にたくさんの情報をセットしてくれます。なので、Pythonの &lt;code&gt;os.environ&lt;/code&gt; を使ってそれらの情報を拾っていきます。Xcodeがセットしてくれる環境変数については&lt;a href="http://developer.apple.com/library/ios/#documentation/DeveloperTools/Reference/XcodeBuildSettingRef/0-Introduction/introduction.html"&gt;http://developer.apple.com/library/ios/#documentation/DeveloperTools/Reference/XcodeBuildSettingRef/0-Introduction/introduction.html&lt;/a&gt;にまとめがあります。&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-python linenums"&gt;#! /usr/bin/env python&lt;br /&gt;# coding: utf-8&lt;br /&gt;&lt;br /&gt;import os&lt;br /&gt;import shutil&lt;br /&gt;from optparse import OptionParser&lt;br /&gt;&lt;br /&gt;def main():&lt;br /&gt;    # Option parser settings&lt;br /&gt;    #&lt;br /&gt;    description = """Sample build script"""&lt;br /&gt;    package_type_choices = (&lt;br /&gt;            'plain',&lt;br /&gt;            'crypted',&lt;br /&gt;    )&lt;br /&gt;    parser = OptionParser(description=description)&lt;br /&gt;    parser.add_option('-t', '--type',&lt;br /&gt;            action='store',&lt;br /&gt;            type='choice',&lt;br /&gt;            choices=package_type_choices,&lt;br /&gt;            default=package_type_choices[0],&lt;br /&gt;            dest='package_type',&lt;br /&gt;            help='Type of the destination package',&lt;br /&gt;            metavar='TYPE')&lt;br /&gt;    (options, args) = parser.parse_args()&lt;br /&gt;    print "*** Begin packaging resources. Package type is %s. ***" % options.package_type&lt;br /&gt;    # Env var settings&lt;br /&gt;    #&lt;br /&gt;    src_resources_path = "%s/Resources/MyResources" % (&lt;br /&gt;            os.environ['SRCROOT'],&lt;br /&gt;    )&lt;br /&gt;    destination_resources_path = "%s/%s/MyResources" % (&lt;br /&gt;            os.environ['TARGET_BUILD_DIR'],&lt;br /&gt;            os.environ['UNLOCALIZED_RESOURCES_FOLDER_PATH']&lt;br /&gt;    )&lt;br /&gt;    # Create target dir&lt;br /&gt;    #&lt;br /&gt;    print "*** Creating the destination MyResources directory at %s ***" % destination_resources_path&lt;br /&gt;    if os.path.isdir(destination_resources_path):&lt;br /&gt;        shutil.rmtree(destination_resources_path)&lt;br /&gt;    os.mkdir(destination_resources_path)&lt;br /&gt;    # Copy each resources in src_resources_path to the destination&lt;br /&gt;    #&lt;br /&gt;    for root, dirs, files in os.walk(src_resources_path):&lt;br /&gt;        for dir in dirs:&lt;br /&gt;            # TODO: This implementation is only for 'plain' packaging. Implement the 'crypted' packaging later&lt;br /&gt;            print "*** Copying the resource %s to the target build location ***" % dir&lt;br /&gt;            fromdir_path = os.path.join(root, dir)&lt;br /&gt;            todir_path = os.path.join(destination_resources_path, dir)&lt;br /&gt;            shutil.copytree(fromdir_path, todir_path)&lt;br /&gt;            print "*** Removing garbage files from the copied resource ***"&lt;br /&gt;            for r, ds, fs in os.walk(todir_path):&lt;br /&gt;                for f in fs:&lt;br /&gt;                    # .から始まるファイルをゴミファイルと見なしてパッケージに加えないようにします&lt;br /&gt;                    if f.startswith('.'):&lt;br /&gt;                        os.remove(os.path.join(r,f))&lt;br /&gt;                        print os.path.join(r,f)&lt;br /&gt;        # Make sure not to traverse into the subdirectories&lt;br /&gt;        del dirs[0:len(dirs)]&lt;br /&gt;    # Completed&lt;br /&gt;    #&lt;br /&gt;    print "*** Packaging resources is successfully completed! ***"&lt;br /&gt;&lt;br /&gt;if __name__ == "__main__":&lt;br /&gt;    main()&lt;/pre&gt;はい、できました。Pythonを使ったメリットとして、 optparse モジュールのおかげでオプションを扱うのがすごく楽にできるとか、リストを扱うのが強力とかが見て取れます。ファイル名の文字列加工も shやcsh の中で sed を使うより安全でらくちんです。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■Xcodeから呼び出す&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;あとはこれをXcodeのビルド時に呼び出すようにしてやれば良いだけです。&lt;br /&gt;&lt;br /&gt;Xcode 3の場合には、画面左のナビゲーションバーからターゲットを選択して、「新規ビルドフェーズを追加」→「スクリプトの実行」とかで出来たと思います。&lt;br /&gt;Xcode 4の場合には、以下の画像が示すとおりにすればOKです。&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-CQVZeoavU_I/TYCzkcf56WI/AAAAAAAAClE/BS16CVG62yg/s1600/callingbuildscriptfrombuildphase.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 258px;" src="http://1.bp.blogspot.com/-CQVZeoavU_I/TYCzkcf56WI/AAAAAAAAClE/BS16CVG62yg/s400/callingbuildscriptfrombuildphase.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5584660976646089058" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;はい、出来ました。あとはビルドするたびに毎回このスクリプトが実行されてくれるわけです。&lt;br /&gt;&lt;br /&gt;画像では紹介してないですが、もちろん呼び出し時にオプションをつけたりできますよ。&lt;pre&gt;/usr/bin/env python $SRCROOT/bin/mybuildscript.py --myoption=1 -v --enable_my_secret&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-5748448958686634856?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/5748448958686634856/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=5748448958686634856' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/5748448958686634856'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/5748448958686634856'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/03/python-xcode.html' title='Python で Xcode のビルドスクリプトを書く方法'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-CQVZeoavU_I/TYCzkcf56WI/AAAAAAAAClE/BS16CVG62yg/s72-c/callingbuildscriptfrombuildphase.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-4152957485701813438</id><published>2011-03-16T20:45:00.005+09:00</published><updated>2011-03-16T21:07:30.413+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='clang'/><category scheme='http://www.blogger.com/atom/ns#' term='Xcode'/><category scheme='http://www.blogger.com/atom/ns#' term='設定'/><category scheme='http://www.blogger.com/atom/ns#' term='Xcode 4.0'/><title type='text'>LLVM compiler 2.0 (clang 2.9) で linker にパスを出力させる方法</title><content type='html'>Xcode 4 から使えるようになった LLVM compiler 2.0 (clang 2.9) の覚え書きです。リンカにパスを出力させる方法を調べてみました。&lt;br /&gt;&lt;br /&gt;※ clang 2.8 じゃなくて 2.9 がベースになってるみたいです。ごめんなさい＞＜&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-ypbK7szPhzw/TYCka1LcLPI/AAAAAAAACk0/cKapPhP2_hY/s1600/vxlinkerv.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 261px;" src="http://2.bp.blogspot.com/-ypbK7szPhzw/TYCka1LcLPI/AAAAAAAACk0/cKapPhP2_hY/s400/vxlinkerv.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5584644318798032114" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;方法は簡単。ビルド設定中のOther Linker Flags (OTHER_LDFLAGS) に、&lt;pre&gt;-v -Xlinker -v&lt;/pre&gt;または&lt;pre&gt;-v -Wl,-v&lt;/pre&gt;を与えればOKです。&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-t_nUKTXgf3E/TYCn8Xmt27I/AAAAAAAACk8/MMV5SuA8CqQ/s1600/vxlinkervresult.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 394px;" src="http://1.bp.blogspot.com/-t_nUKTXgf3E/TYCn8Xmt27I/AAAAAAAACk8/MMV5SuA8CqQ/s400/vxlinkervresult.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5584648193509809074" /&gt;&lt;/a&gt;&lt;br /&gt;ほいごらんのとおり。&lt;br /&gt;&lt;br /&gt;gcc 4.2 または LLVM gcc 4.2 を使っているときは、 gcc がコンパイルして ld でリンクするようになっていましたが、 clang を使うときは clang が一人でコンパイルして一人でリンクまでやってしまいます。そのため、これまで通り普通に&lt;code&gt;-v&lt;/code&gt;を渡しただけではうまくいきません。これだと、単に clang が verbose モードになるだけですからね。そこで &lt;code&gt;-Xlinker&lt;/code&gt; とか &lt;code&gt;-Wl&lt;/code&gt; を使ってリンカを verbose モードにすればOKということです。詳細は&lt;code&gt;man clang&lt;/code&gt;すべし。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-4152957485701813438?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/4152957485701813438/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=4152957485701813438' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/4152957485701813438'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/4152957485701813438'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/03/llvm-compiler-20-clang-28-linker.html' title='LLVM compiler 2.0 (clang 2.9) で linker にパスを出力させる方法'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-ypbK7szPhzw/TYCka1LcLPI/AAAAAAAACk0/cKapPhP2_hY/s72-c/vxlinkerv.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-6352039824708006109</id><published>2011-03-08T23:28:00.003+09:00</published><updated>2011-03-15T22:14:15.015+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ライブラリ'/><category scheme='http://www.blogger.com/atom/ns#' term='Xcode'/><category scheme='http://www.blogger.com/atom/ns#' term='Xcode 3.2.5'/><category scheme='http://www.blogger.com/atom/ns#' term='コマンドライン'/><title type='text'>lipo を使って簡単に Universal Binary を作成する方法</title><content type='html'>iOS 向けのライブラリやフレームワークは、よく static library (.aファイル) の形式で配布されています。これは iOS がユーザーが作成した dynamic library (.dylibファイル) や framework バンドルをサポートしていないからなのですが、ときどきこの static library がシミュレーターとデバイス両方で使える形式、いわゆる Universal Binary になっていない場合があります。&lt;br /&gt;&lt;br /&gt;たとえばこんな感じですね。&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-8UJgma7a0hE/TXY9ZnTXTwI/AAAAAAAACkM/4anugW6s3EQ/s1600/beforeusinglipo.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 234px; height: 236px;" src="http://2.bp.blogspot.com/-8UJgma7a0hE/TXY9ZnTXTwI/AAAAAAAACkM/4anugW6s3EQ/s400/beforeusinglipo.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5581716298428534530" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;この状態でビルドを行うと、シミュレーター向けビルドを行えばデバイス用のバイナリが、デバイス向けビルドを行えばシミュレーター用のバイナリが、それぞれ対応していないアーキテクチャであると警告を出してしまいます。警告ですからコンパイルは通るのですが、私は几帳面で気になってしまうので、これを解消したいと考えます。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■lipoの出番&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;そこで lipo を使います。 lipo は Xcode に付属されているコマンドラインツールですので、 iOS SDK をインストールしている人でしたら誰でも使えます。詳しい使い方は man を見ていただければわかりますが、普通使うのは以下のパターンだけです:&lt;pre&gt;lipo -create ライブラリ1.a ライブラリ2.a -output 出力するライブラリ.a&lt;/pre&gt;たったのこれだけで二つのライブラリを組み合わせて Universal Binary を生成してくれます。さっきの画像の例ですと、&lt;pre&gt;lipo -create libAbesi_dev.a libAbesi_sim.a -output libAbesi.a&lt;/pre&gt;これでOKです。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■本当に Universal なの？&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;それでは本当に Universal Build になったのか見てみましょう。 static library の中身を見るには、 nm コマンドを使います。&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-eQu02fseRuY/TXY9Z8yqq1I/AAAAAAAACkU/CqoV2rcdxXA/s1600/testingbynm.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 298px;" src="http://2.bp.blogspot.com/-eQu02fseRuY/TXY9Z8yqq1I/AAAAAAAACkU/CqoV2rcdxXA/s400/testingbynm.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5581716304196971346" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;どうやらうまくいったみたいですね。一つのライブラリファイルの中に、3種類のアーキテクチャに対応したオブジェクトが格納されています。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-6352039824708006109?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/6352039824708006109/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=6352039824708006109' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/6352039824708006109'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/6352039824708006109'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/03/lipo-universal-binary.html' title='lipo を使って簡単に Universal Binary を作成する方法'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-8UJgma7a0hE/TXY9ZnTXTwI/AAAAAAAACkM/4anugW6s3EQ/s72-c/beforeusinglipo.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-8589603972720871910</id><published>2011-02-28T00:18:00.011+09:00</published><updated>2011-02-28T00:46:23.960+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tips'/><category scheme='http://www.blogger.com/atom/ns#' term='iOS 4.2.1'/><category scheme='http://www.blogger.com/atom/ns#' term='Cocoa'/><category scheme='http://www.blogger.com/atom/ns#' term='UI'/><title type='text'>UIWebView のスクロールを制御するためのプロパティを書いてみた</title><content type='html'>UIWebView にどうして scrollEnabled プロパティがついてねえんだ Apple のチンパンジー野郎！とお嘆きの全国1000万の iOS 開発者の皆様、こんばんわ。もちろん私もその一人であります。&lt;br /&gt;&lt;br /&gt;嘆いていてもしょうがないので何とかスクロールを制御する方法を・・・と思って探していたら、すでに2009年の地点で &lt;a href="http://twitter.com/nakamura001"&gt;@nakamura001&lt;/a&gt; さんがこんなブログを書いてらっしゃいました。&lt;br /&gt;&lt;br /&gt;&lt;a href="http://d.hatena.ne.jp/nakamura001/20090520/1242837408"&gt;http://d.hatena.ne.jp/nakamura001/20090520/1242837408&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;が、遷移先で詳解されている&lt;br /&gt;&lt;br /&gt;&lt;a href="http://praveenmatanam.wordpress.com/2009/04/03/how-to-disable-uiwebview-from-user-scrolling/"&gt;http://praveenmatanam.wordpress.com/2009/04/03/how-to-disable-uiwebview-from-user-scrolling/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;のコードが正直いまいちなのです。何がいまいちって、せっかくのCocoa環境であるにも関わらず、わざわざ&lt;code&gt;objc/runtime.h&lt;/code&gt;なんていう低レベルなC言語の関数を使っています。別にパフォーマンスがタイトな場所でもないですし、かっこよくCocoaっぽく書き直してみました。ということで書き直したコードがこちら↓&lt;br /&gt;&lt;br /&gt;&lt;a href="https://gist.github.com/846258"&gt;https://gist.github.com/846258&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;で、このAdditionを導入するとですね、&lt;pre class="prettyprint lang-m linenums"&gt;UIWebView *webView = [[[UIWebView alloc] initWithFrame:frame] autorelease];&lt;br /&gt;webView.webViewScrollEnabled = NO;&lt;/pre&gt;みたいな書き方ができてハッピーになれます。&lt;br /&gt;&lt;br /&gt;内部的には NSInvocation を使っています。 Mac OS X 10.5 (iOS 2.0) から存在するこのクラス、本当に便利で、ぶっちゃけ呼び出し対象のシグネチャさえわかれば何でも呼び出せるスグレモノです。フレームワークを作るときなど、呼び出し先のシグネチャしかわからない状況下で対象のメソッドを呼び出す時などに便利な感じかもです。その上 NSInvocationOperation を使ってそのまま並列化もできたりして。&lt;pre class="prettyprint lang-m linenums:1"&gt;NSMethodSignature *sig = [subview methodSignatureForSelector:selector];&lt;br /&gt;NSInvocation* invocation = [NSInvocation invocationWithMethodSignature:sig];&lt;br /&gt;[invocation setTarget:subview];&lt;br /&gt;[invocation setSelector:selector];&lt;br /&gt;[invocation invoke];&lt;br /&gt;BOOL result = YES;&lt;br /&gt;[invocation getReturnValue:&amp;result];&lt;br /&gt;return result;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-8589603972720871910?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/8589603972720871910/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=8589603972720871910' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/8589603972720871910'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/8589603972720871910'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/02/uiwebview.html' title='UIWebView のスクロールを制御するためのプロパティを書いてみた'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-2145533581542277569</id><published>2011-02-20T22:43:00.003+09:00</published><updated>2011-02-20T22:53:14.021+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='git'/><category scheme='http://www.blogger.com/atom/ns#' term='github'/><category scheme='http://www.blogger.com/atom/ns#' term='チュートリアル'/><title type='text'>github で pull request をされたとき・するときの手順</title><content type='html'>github に自分のリポジトリを公開していると、たまに pull request をされることがあります。また逆に、他人のリポジトリのコードを使っていて、どうしても気になるバグを見つけて修正したときなど、相手に pull request を送りたいことがあります。こんなときにどうすればよいかをまとめてみました。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■pull request をしたいとき&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;pull request をしたいときは、まず相手のリポジトリを fork する必要があります。&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-Ppv2ApbeuVo/TWEbL3vV1II/AAAAAAAACjc/b6iiKE7QP8k/s1600/pullrequest1.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 84px;" src="http://4.bp.blogspot.com/-Ppv2ApbeuVo/TWEbL3vV1II/AAAAAAAACjc/b6iiKE7QP8k/s400/pullrequest1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5575767704416408706" /&gt;&lt;/a&gt;&lt;br /&gt;このボタンをぽちっとな。&lt;br /&gt;&lt;br /&gt;fork したら、 fork して自分の管理下に入ったリポジトリを clone して、コードを修正します。&lt;pre&gt;git clone https://akisute@github.com/akisute/asi-http-request.git&lt;/pre&gt;コードの修正が終わったら、自分の fork したリポジトリに push しておきます。&lt;pre&gt;git push origin master&lt;/pre&gt;ではコードの修正が終わったので pull request をします。&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-bPdCZPUzTlA/TWEbMGaL7RI/AAAAAAAACjk/OVSzsxi-Af0/s1600/pullrequest2.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 130px;" src="http://3.bp.blogspot.com/-bPdCZPUzTlA/TWEbMGaL7RI/AAAAAAAACjk/OVSzsxi-Af0/s400/pullrequest2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5575767708354211090" /&gt;&lt;/a&gt;&lt;br /&gt;このボタンをぽちっとな。&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-q1EJjZA1BAQ/TWEbMIbGYCI/AAAAAAAACjs/2GrKSM_exuI/s1600/pullrequest3.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 243px;" src="http://2.bp.blogspot.com/-q1EJjZA1BAQ/TWEbMIbGYCI/AAAAAAAACjs/2GrKSM_exuI/s400/pullrequest3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5575767708894912546" /&gt;&lt;/a&gt;&lt;br /&gt;するとこうなります。デフォルトでは相手の master に対して自分の master を pull request することになりますが、もちろんこの画面で変更可能です。 request をする先のリポジトリ・ブランチと、リクエストされるブランチをそれぞれ指定できます。それからコメントをつけて送れます。ここでつけたコメントは相手側のリポジトリの Pull Requests タブに記載されるので、それなりにかっこいい内容を書いておくと良いかと思います。あとは相手が受け入れてくれるのを待つばかりです。自分のコメントにコメントがついたらメールとかで通知が来ますんで、適当に返事して相手と連絡を取りながらやる感じになります。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■pull request をされたとき&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;逆に自分が pull request をされることもありますので、そのときの対処法も。&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-xlBWlwLbP3I/TWEbMSCHfQI/AAAAAAAACj0/_4Al6u0DgGE/s1600/pullrequest4.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 126px;" src="http://4.bp.blogspot.com/-xlBWlwLbP3I/TWEbMSCHfQI/AAAAAAAACj0/_4Al6u0DgGE/s400/pullrequest4.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5575767711474482434" /&gt;&lt;/a&gt;&lt;br /&gt;pull request されると、こんな風に Inbox の Notifications の中に通知が来ます。&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-w4lCm-Cvg8Y/TWEbMr1zhbI/AAAAAAAACj8/PUPSFCoVXdQ/s1600/pullrequest5.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 156px;" src="http://1.bp.blogspot.com/-w4lCm-Cvg8Y/TWEbMr1zhbI/AAAAAAAACj8/PUPSFCoVXdQ/s400/pullrequest5.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5575767718402164146" /&gt;&lt;/a&gt;&lt;br /&gt;対象のリポジトリの Pull Requests タブにもこんな具合でリクエストが入ります。&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-36vWjPxBAag/TWEcTTcjUMI/AAAAAAAACkE/uXXi-iAGapY/s1600/pullrequest6.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 180px;" src="http://4.bp.blogspot.com/-36vWjPxBAag/TWEcTTcjUMI/AAAAAAAACkE/uXXi-iAGapY/s400/pullrequest6.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5575768931624505538" /&gt;&lt;/a&gt;&lt;br /&gt;クリックしてリクエストの詳細を開きます。ファイルの diff 一覧とかどっからどこに対してリクエストが飛んでいるのよとか全部ここで見られます。相手のコメントに対してコメントを返したり、 diff に対してコメントをつけたりできます。 diff につけたコメントは相手にも公表されます。&lt;br /&gt;&lt;br /&gt;ここで相手とコメントやりとりとかして、じゃあ取り込もうか、となりましたら、実際に pull request を取り込む作業を行います。自分のリポジトリにマージ用のブランチを用意して、 pull して確認し、問題なければマージ用のブランチと本線をマージして終了。コマンドがよくわからなくても github が全てのコマンドを表示してくれるのでそれを見れば一発です。本当に親切。以下、 master ブランチに対して pull request があったとすると、&lt;pre&gt;git checkout -b pull-request-master master&lt;br /&gt;git pull http://github.com/applicant/his-repository&lt;br /&gt;# 相手のコミットが自分のブランチに pull されてくるので、この状態で動作を確認する&lt;br /&gt;# merge 作業が発生するならここで行う&lt;br /&gt;# 問題がなさそうなら&lt;br /&gt;git commit&lt;br /&gt;git merge master&lt;br /&gt;git push origin master&lt;/pre&gt;push まで完了したら先ほどの pull request のページから取り込み完了したよボタンを押しておきましょう。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■おまけ: 自分が fork しているコードの fork 元リポジトリが更新されたので、こちらも最新にしたい&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;実はこれは pull request をされたときとあんまり変わりません。対象の相手のブランチを自分の fork しているコードに pull すればよいのです。&lt;pre&gt;git checkout -b merge-master master&lt;br /&gt;git pull http://github.com/parent/parent-repository&lt;br /&gt;# 相手のコミットが自分のブランチに pull されてくるので、この状態で動作を確認する&lt;br /&gt;# merge 作業が発生するならここで行う&lt;br /&gt;# 問題がなさそうなら&lt;br /&gt;git commit&lt;br /&gt;git merge master&lt;br /&gt;git push origin master&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-2145533581542277569?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/2145533581542277569/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=2145533581542277569' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/2145533581542277569'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/2145533581542277569'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/02/github-pull-request.html' title='github で pull request をされたとき・するときの手順'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-Ppv2ApbeuVo/TWEbL3vV1II/AAAAAAAACjc/b6iiKE7QP8k/s72-c/pullrequest1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-4180857410109216588</id><published>2011-02-12T14:37:00.004+09:00</published><updated>2011-02-12T15:38:54.104+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='Redmine'/><category scheme='http://www.blogger.com/atom/ns#' term='インストール'/><title type='text'>Redmine を Debian 5.0 にゼロからインストールしてみた</title><content type='html'>あらかじめ注意: 下記のメモは、ruby, gem, rails, rack, redmineのいずれかのバージョンが0.0.1でも違うと動作しない可能性が高いので、当てにしないでください。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■顧客が説明した要件&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;1つのサーバーに複数のプロジェクトのリポジトリとかリソースをおいているので、1プロジェクトにつき1個インスタンスが必要なtracは都合が悪い！&lt;/li&gt;&lt;li&gt;っていうかtrac飽きた！！古い！&lt;/li&gt;&lt;li&gt;複数プロジェクト扱えるBTSが欲しい&lt;/li&gt;&lt;li&gt;見た目クールだといいね、カスタマイズとかできるとすごくいい！&lt;/li&gt;&lt;li&gt;Wikiは絶対必須&lt;/li&gt;&lt;li&gt;Google Appsと連携できると素敵だな！&lt;/li&gt;&lt;li&gt;簡単にインストールしたい、時間かけたくない&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■プロジェクトリーダーの理解&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="https://www.gravitydev.com/"&gt;https://www.gravitydev.com/&lt;/a&gt; はすごくいいんだけれど許可下りなさそうだなぁ。そもそもWikiがないから却下。&lt;/li&gt;&lt;li&gt;となるとやっぱりRedmineかな！あれすごくいいよね！&lt;/li&gt;&lt;li&gt;Redmineに移行しようかみたいな話も社内で出てたし、先んじて導入してノウハウ作るのはありだな！&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■アナリストのデザイン&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;[11/02/10 9:24:53] akisute: redmineのインストールが超面倒くさいんだけれど&lt;br /&gt;[11/02/10 9:24:54] akisute: なんとかならんのこれ&lt;br /&gt;[11/02/10 9:25:02] wozozo ( ﾟДﾟ)y─┛~~: rails&lt;br /&gt;[11/02/10 9:25:19] tokibito: rails&lt;br /&gt;[11/02/10 9:25:20] 文 殊堂: まいんちゃん&lt;br /&gt;[11/02/10 9:26:39] akisute: http://redmine.jp/guide/RedmineInstall/&lt;br /&gt;[11/02/10 9:26:43] akisute: これ見てるとアホかと言いたくなってくる&lt;br /&gt;[11/02/10 9:26:50] akisute: Ruby 1.9には対応していません。 上記の表に示したバージョンのRuby 1.8.xをインストールしてください。&lt;br /&gt;RubyGems 1.3.1以上が必要です。&lt;br /&gt;Rake 0.8.3以上が必要です。&lt;br /&gt;Rack 1.0.1が必要です。1.0.1がインストールされていない場合、データベースマイグレーションが失敗します。&lt;br /&gt;[11/02/10 9:27:25] wozozo ( ﾟДﾟ)y─┛~~: aptでいれたgemをupdateしようとすると、&lt;br /&gt;[11/02/10 9:27:34] wozozo ( ﾟДﾟ)y─┛~~: おい待てって言われるし&lt;br /&gt;[11/02/10 9:27:49] aodag: Redmineってライトニングなのないの？&lt;br /&gt;[11/02/10 9:27:53] tokibito: rubyはaptで入れたら死亡する可能性&lt;br /&gt;[11/02/10 9:28:04] aodag: rvmっしょ&lt;br /&gt;[11/02/10 9:28:04] tokibito: 自分でビルドしたほうが無難とかいう&lt;br /&gt;[11/02/10 9:28:11] tokibito: rvmで。&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■プログラマのコード&lt;/span&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;redmine:redmine ユーザーを新規に作成する&lt;ul&gt;&lt;li&gt;以下の作業はすべてredmineユーザーで行う&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;rvmの最新をインストールする&lt;ul&gt;&lt;li&gt;&lt;a href="http://rvm.beginrescueend.com/rvm/install/"&gt;http://rvm.beginrescueend.com/rvm/install/&lt;/a&gt;&lt;/li&gt;&lt;li&gt;curl と git-core のインストールが必要。aptitude経由で実施&lt;/li&gt;&lt;li&gt;/home/redmine/.bashrcの追記を忘れないように&lt;/li&gt;&lt;li&gt;source ~/.rvm/scripts/rvm も忘れないように&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;rvmに必要なパッケージをインストールする&lt;ul&gt;&lt;li&gt;こんなんデフォルトで用意しろよ・・・いいかげんにしろ・・・&lt;/li&gt;&lt;li&gt;rvm package install readline&lt;/li&gt;&lt;li&gt;rvm package install iconv&lt;/li&gt;&lt;li&gt;rvm package install zlib&lt;/li&gt;&lt;li&gt;rvm package install openssl&lt;/li&gt;&lt;li&gt;この順番で入れないと依存関係の問題で怒られます (opensslがzlibを使うとか)&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;ruby 1.8.7 をrvm経由でインストールする&lt;ul&gt;&lt;li&gt;参考は &lt;a href="http://d.hatena.ne.jp/masasuz/20100720/1279635055"&gt;http://d.hatena.ne.jp/masasuz/20100720/1279635055&lt;/a&gt;&lt;/li&gt;&lt;li&gt;先に rvm package install しないとgemが使えない, zlibがないので&lt;/li&gt;&lt;li&gt;ビルドオプションを付けることでopensslとzlibを有効にすること&lt;/li&gt;&lt;li&gt;rvm install 1.8.7 -C --with-openssl-dir=$HOME/.rvm/usr -C --with-zlib-dir=$HOME/.rvm/usr&lt;/li&gt;&lt;li&gt;rvm use 1.8.7&lt;/li&gt;&lt;li&gt;ruby --version&lt;/li&gt;&lt;li&gt;gem --version&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;gemのバージョンを 1.3.7 に戻す&lt;ul&gt;&lt;li&gt;gemのバージョンが1.5の場合、rails 2.3.5が動かないので、バージョンを戻す（何だこのジョーク）&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.oiax.jp/rails/zakkan/rubygems_1_5.html"&gt;http://www.oiax.jp/rails/zakkan/rubygems_1_5.html&lt;/a&gt;&lt;/li&gt;&lt;li&gt;gem install rubygems-update -v=1.3.7&lt;/li&gt;&lt;li&gt;update_rubygems&lt;/li&gt;&lt;li&gt;gem --version&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;本当にopensslとかzlibとかインストールされているかをチェックする&lt;ul&gt;&lt;li&gt;ruby -r openssl -e ""&lt;/li&gt;&lt;li&gt;エラーになった場合はopensslの再ビルドを行う。opensslを使えるようにしないとのちのちrakeを実行するところでエラーが発生して先に進めなくなる&lt;/li&gt;&lt;li&gt;cd ~/.rvm/src/ruby-1.8.7-p330/ext/openssl&lt;/li&gt;&lt;li&gt;ruby extconf.rb --with-opt-dir=$HOME/.rvm/usr/&lt;/li&gt;&lt;li&gt;make&lt;/li&gt;&lt;li&gt;make install&lt;/li&gt;&lt;li&gt;ruby -r openssl -e "" を再度実行してエラーにならない事を確認&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;rails 2.3.5 をgem経由でインストールする&lt;ul&gt;&lt;li&gt;gem install rails -v=2.3.5&lt;/li&gt;&lt;li&gt;rails 2.3.5をインストールすると自動的にrack 1.0.1が入るが、先にrack 1.0.1をインストールしておいたほうが良いかも&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;rack 1.0.1 をgem経由でインストールする&lt;ul&gt;&lt;li&gt;gem install rack -v=1.0.1&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;sqlite3-ruby 1.2.3 をgem経由でインストールする&lt;ul&gt;&lt;li&gt;参考は &lt;a href="http://d.hatena.ne.jp/modka/20101208"&gt;http://d.hatena.ne.jp/modka/20101208&lt;/a&gt;&lt;/li&gt;&lt;li&gt;sqlite3-devel (sqlite3.h) が見つからないとインストール出来ないので注意&lt;/li&gt;&lt;li&gt;最新のsqlite3-ruby は sqlite3 3.6.3 が必要で、Debianのaptitudeでは3.5.9までしか無いので、バージョンを指定して古いsqlite3-rubyを入れる&lt;/li&gt;&lt;li&gt;sudo aptitude install sqlite3&lt;/li&gt;&lt;li&gt;sudo aptitude install libsqlite3-dev&lt;/li&gt;&lt;li&gt;gem install sqlite3-ruby -v=1.2.3&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;i18n 0.4.2 をgem経由でインストールする&lt;ul&gt;&lt;li&gt;rakeの実行に必要&lt;/li&gt;&lt;li&gt;rakeお前依存関係に含めろや・・・アホか・・・＞＜&lt;/li&gt;&lt;li&gt;gem install i18n -v=0.4.2&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;redmine のリリース版の最新をダウンロードする&lt;ul&gt;&lt;li&gt;cd ~/&lt;/li&gt;&lt;li&gt;&lt;a href="http://rubyforge.org/frs/?group_id=1850"&gt;http://rubyforge.org/frs/?group_id=1850&lt;/a&gt; に Redmine のビルドがあります&lt;/li&gt;&lt;li&gt;wget &lt;a href="http://rubyforge.org/frs/download.php/74130/redmine-1.1.1.zip"&gt;http://rubyforge.org/frs/download.php/74130/redmine-1.1.1.zip&lt;/a&gt;&lt;/li&gt;&lt;li&gt;unzip redmine-1.1.1.zip&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;データベースの設定を行う&lt;ul&gt;&lt;li&gt;参考は &lt;a href="http://redmine.jp/guide/RedmineInstall/"&gt;http://redmine.jp/guide/RedmineInstall/&lt;/a&gt;&lt;/li&gt;&lt;li&gt;今回はsqlite3&lt;/li&gt;&lt;li&gt;cd ~/redmine-1.1.1/config&lt;/li&gt;&lt;li&gt;cp database.yml.example database.yml&lt;/li&gt;&lt;li&gt;vim database.yml&lt;/li&gt;&lt;li&gt;cd ~/redmine-1.1.1&lt;/li&gt;&lt;li&gt;rake generate_session_store&lt;/li&gt;&lt;li&gt;rake db:migrate RAILS_ENV="production"&lt;/li&gt;&lt;li&gt;rake redmine:load_default_data RAILS_ENV="production"&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;メールの送信設定を行う&lt;ul&gt;&lt;li&gt;不要と思われる。メールが飛ばないだけで済む&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;起動する&lt;ul&gt;&lt;li&gt;cd ~/redmine-1.1.1/&lt;/li&gt;&lt;li&gt;ruby script/server webrick -e production&lt;/li&gt;&lt;li&gt;&lt;a href="http://localhost:3000/"&gt;http://localhost:3000/&lt;/a&gt; が立ち上がるので、 admin/admin でログインする&lt;/li&gt;&lt;li&gt;適切にadminのパスワードを変更すること&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;ログの設定を行う&lt;ul&gt;&lt;li&gt;やっとかないとログが溜まりまくって死ぬらしいので&lt;/li&gt;&lt;li&gt;cd ~/redmine-1.1.1/config&lt;/li&gt;&lt;li&gt;cp additional_environment.rb.example additional_environment.rb&lt;/li&gt;&lt;li&gt;vim additional_environment.rb&lt;/li&gt;&lt;li&gt;&lt;a href="http://redmine.jp/guide/RedmineInstall/"&gt;http://redmine.jp/guide/RedmineInstall/&lt;/a&gt; のログの設定セクションのとおりに設定しておく&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Passengerをインストールする&lt;ul&gt;&lt;li&gt;参考は &lt;a href="http://d.hatena.ne.jp/Umeyashiki/20100131/1264948069"&gt;http://d.hatena.ne.jp/Umeyashiki/20100131/1264948069&lt;/a&gt;&lt;/li&gt;&lt;li&gt;gem install passenger&lt;/li&gt;&lt;li&gt;passenger-install-nginx-module&lt;/li&gt;&lt;li&gt;ここまでの手順どおりに進めていると、大体以下のものが足りないはず&lt;ul&gt;&lt;li&gt;Curl development headers with SSL support... not found&lt;/li&gt;&lt;li&gt;OpenSSL development headers... not found&lt;/li&gt;&lt;li&gt;Zlib development headers... not found&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;一旦abortしてそれぞれインストールすること&lt;ul&gt;&lt;li&gt;sudo aptitude install zlib1g-dev&lt;/li&gt;&lt;li&gt;sudo aptitude install libssl-dev&lt;/li&gt;&lt;li&gt;sudo aptitude install libcurl4-openssl-dev&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;nginxの再ビルド（ないしソースコード）が必要になるので、すでにapt-getしたnginxがある場合には使えない。その場合はpassengerをstandaloneで起動して、そこに対してnginxからproxy-passなりなんなりする。&lt;/li&gt;&lt;li&gt;以下、passengerスタンドアロンで起動し、redmineはすべてpassengerにやらせる場合を考えます。ただしpassengerのスタンドアロンは内部的にはnginxを使っているので、いずれにせよ上記のインストールは必要になります。&lt;/li&gt;&lt;li&gt;cd ~/&lt;/li&gt;&lt;li&gt;mkdir log run&lt;/li&gt;&lt;li&gt;passenger start redmine1.1.1 -d -a 0.0.0.0 -p 3000 -e production --log-file=log/passenger.log --pid-file=run/passenger.pid&lt;/li&gt;&lt;li&gt;ってやると何故か/tmp以下にlogファイルをつくろうとしていみわからないエラー吐いて死ぬので中止&lt;/li&gt;&lt;li&gt;cd ~/redmine1.1.1&lt;/li&gt;&lt;li&gt;passenger start -d -e production&lt;/li&gt;&lt;li&gt;最低限のオプションだけで起動すれば起動できた&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■営業の表現、約束&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;お客様、 redmine をお求めですか？ご安心ください！ &lt;code&gt;gem install redmine&lt;/code&gt; で一発に決まってますよ！簡単です！&lt;ul&gt;&lt;li&gt;そんなものはない&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;それなら &lt;code&gt;sudo apt-get install redmine&lt;/code&gt; で一発です！猿でもインストールできます！！&lt;ul&gt;&lt;li&gt;Debian では無理&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;それなら最初から redmine がインストールされている vm イメージがあります！こちらを使えば一発です！&lt;ul&gt;&lt;li&gt;Ubuntu と SUSE しかない&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://sourceforge.jp/projects/traclight/wiki/FrontPage"&gt;Trac Lightning&lt;/a&gt; とかゆとり。真のエンジニアは ruby の configure &amp; build から自分でやって当然（キリッ&lt;ul&gt;&lt;li&gt;そんな業務と関係ないところに何時間（何万円）使うつもり？&lt;/li&gt;&lt;li&gt;アップデートどうすんの？何時間（何万円）使うつもり？&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■プロジェクトの書類&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://redmine.jp/guide/"&gt;http://redmine.jp/guide/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■実装された運用&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.redmine.org/projects/redmine"&gt;http://www.redmine.org/projects/redmine&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■顧客への請求金額&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;akisute の実働5時間分 = 数万円 = &lt;a href="https://www.gravitydev.com/pricing"&gt;https://www.gravitydev.com/pricing&lt;/a&gt; のスタンダードプラン数年分&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■得られたサポート&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://redmine.jp/guide/RedmineInstall/"&gt;http://redmine.jp/guide/RedmineInstall/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■顧客が本当に必要だったもの&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://twitter.com/shin_no_suke/status/35632371084562433"&gt;http://twitter.com/shin_no_suke/status/35632371084562433&lt;/a&gt;&lt;br /&gt;&lt;a href="http://twitter.com/hirokinko/status/36307730025156608"&gt;http://twitter.com/hirokinko/status/36307730025156608&lt;/a&gt;&lt;br /&gt;&lt;a href="http://twitter.com/hirokinko/status/36310634127695872"&gt;http://twitter.com/hirokinko/status/36310634127695872&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■元ネタ&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://ryonoda.wordpress.com/2008/09/26/"&gt;http://ryonoda.wordpress.com/2008/09/26/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■一応補足&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Redmine自体はすごく良いアプリだと思います。ええ。いま使ってますが、とっても助かってます。&lt;br /&gt;&lt;br /&gt;bitnamiの配布しているパッケージが対話環境でもインストールできるというのは知りませんでした。っていうかbitnamiのページのどこにも書いてないんですが・・・＞＜&lt;pre&gt;wget http://bitnami.org/files/stacks/redmine/1.1.1-0/bitnami-redmine-1.1.1-0-linux-installer.bin&lt;br /&gt;chmod +x bitnami-redmine-1.1.1-0-linux-installer.bin&lt;br /&gt;./bitnami-redmine-1.1.1-0-linux-installer.bin --mode text&lt;/pre&gt;でうまくいくようです。&lt;br /&gt;&lt;br /&gt;しかしこの方法を使うと勝手にApache, MySQL, Ruby, Subversionをインストールされてしまうみたいなので、きちんと管理したいとなるとちょっと不向きかなと。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-4180857410109216588?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/4180857410109216588/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=4180857410109216588' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/4180857410109216588'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/4180857410109216588'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/02/redmine-debian-40.html' title='Redmine を Debian 5.0 にゼロからインストールしてみた'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-2508726479659951005</id><published>2011-02-09T22:02:00.000+09:00</published><updated>2011-02-09T22:03:20.596+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='バグ'/><category scheme='http://www.blogger.com/atom/ns#' term='iOS 4.2.1'/><category scheme='http://www.blogger.com/atom/ns#' term='Cocoa'/><title type='text'>UITableView の cell の中に UITextView を配置したとき発生する問題とその対処方法</title><content type='html'>たとえば Twitter クライアントや SMS クライアントのように、短い文章を入力させるような画面を作りたいとき, Grouped Style な UITableView の cell の中に UITextView を配置して画面を作る事が良くあるかと思います。通常、この作りでほとんど問題はありませんが、特定の条件下で問題が発生することがわかりましたので、回避策をメモしておきます。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■問題&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;この問題が発生するのは、以下の条件を満たしたときです。&lt;ol&gt;&lt;li&gt;UITableView の cell の中に UITextView を配置する。&lt;/li&gt;&lt;li&gt;UITextView に、縦スクロールが発生するぐらい長い文字列を入力する。&lt;/li&gt;&lt;li&gt;UITextView の中ほどにカーソルを移動する。&lt;/li&gt;&lt;li&gt;UITableView と UITextView の scrollEnabled プロパティを NO に設定する。&lt;/li&gt;&lt;li&gt;UITextView の text プロパティを変更する。&lt;/li&gt;&lt;/ol&gt;すると, UITextView および UITableView の scrollEnabled プロパティを NO に設定しているにもかかわらず、勝手に UITableView がスクロールを起こしてしまいます。 UITextView の text プロパティを書き換えたら勝手に UITextView が一番下までスクロールしてしまうのはデフォルトの挙動であり、これは問題ありません. UITextView を単品で使っているときは, scrollEnabled プロパティを NO に設定することでスクロールを発生させずに text を書き換えることが可能なのですが, UITextView を UITableView の中に含めたときのみ, scrollEnabled プロパティが無視されてしまい、この問題が発生してしまうようです。&lt;br /&gt;&lt;br /&gt;カスタムキーボードを用意したり、本文中のURLを短縮して差し替えたりなど、結構 UITextView の text プロパティを直接書き換えたい要件があったりするので、このままでは困ります。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■解決方法&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;そこで、相当な荒技ですが、以下のようにして解決を図ることが可能です。&lt;ol&gt;&lt;li&gt;UITableView の cell の中に UITextView を配置する。&lt;/li&gt;&lt;li&gt;UITextView をいったん removeFromSuperview する。&lt;/li&gt;&lt;li&gt;UITextView をいったん UITableView 以外の場所に addSubview する。&lt;ul&gt;&lt;li&gt;UIWindow の直下などがおすすめ。&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;UITextView の scrollEnabled プロパティを NO に設定する。&lt;/li&gt;&lt;li&gt;UITextView の text プロパティを変更する。&lt;/li&gt;&lt;li&gt;UITextView の scrollEnabled プロパティを YES に設定する。&lt;/li&gt;&lt;li&gt;UITextView を元の view に addSubview する。&lt;/li&gt;&lt;li&gt;UITextView を first responder にする。&lt;/li&gt;&lt;/ol&gt;コードにすると以下のようになります:&lt;pre&gt;UIView *parentView = textView.superview;&lt;br /&gt;[self.view.window addSubview:textView];&lt;br /&gt;textView.scrollEnabled = NO;&lt;br /&gt;&lt;br /&gt;textView.text = [currentText stringByReplacingCharactersInRange:selectedRange withString:shrunkenURLString];&lt;br /&gt;textView.selectedRange = NSMakeRange(selectedRange.location + [shrunkenURLString length], 0);&lt;br /&gt;&lt;br /&gt;textView.scrollEnabled = YES;&lt;br /&gt;[parentView addSubview:textView];&lt;br /&gt;[textView becomeFirstResponder];&lt;/pre&gt;こうすることで, UITableView が勝手にスクロールしてしまう問題を回避することが可能です。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-2508726479659951005?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/2508726479659951005/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=2508726479659951005' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/2508726479659951005'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/2508726479659951005'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/02/uitableview-cell-uitextview.html' title='UITableView の cell の中に UITextView を配置したとき発生する問題とその対処方法'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-6480269097389308163</id><published>2011-02-04T23:44:00.011+09:00</published><updated>2011-02-05T00:16:18.432+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iPhone'/><category scheme='http://www.blogger.com/atom/ns#' term='iPad'/><category scheme='http://www.blogger.com/atom/ns#' term='開発'/><category scheme='http://www.blogger.com/atom/ns#' term='Webサービス'/><title type='text'>TestFlight 経由のアプリのダウンロード速度を調べてみた</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_9HdIXu4872o/TUwYOWwMUxI/AAAAAAAACjU/5xsyP2wQoe4/s1600/TestFlight%2BLogo.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 306px; height: 81px;" src="http://4.bp.blogspot.com/_9HdIXu4872o/TUwYOWwMUxI/AAAAAAAACjU/5xsyP2wQoe4/s400/TestFlight%2BLogo.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5569853474055410450" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;最近 iOS 界隈を賑わせている &lt;a href="http://testflightapp.com/"&gt;TestFlight&lt;/a&gt; というWebサービスがあります。詳細についてはまぁ &lt;a href="http://jp.techcrunch.com/archives/20110120testflight/"&gt;TechCrunch&lt;/a&gt; さんでも読んでいただくとしまして、この TestFlight が非常に便利そうなので私のほうでも早速試してます。登録も簡単、アプリのマネジメントも良くできていますし、チームを複数用意して管理できるというのも良いです。なんで Apple がデフォルトでこれを用意してくれないのかというぐらい便利です。&lt;br /&gt;&lt;br /&gt;が、一つだけ気になったことがあって、まぁタイトル通りなのですが、&lt;span style="font-weight:bold; color:#cc0000;"&gt;TestFlight経由だとアプリのダウンロードが遅いのではないか？&lt;/span&gt;ということです。ということで実際にやってみました。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■条件&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;対象のアプリのサイズは17.7MB。&lt;br /&gt;以下の2カ所の回線で計測しました。&lt;ul&gt;&lt;li&gt;会社の回線（確かバッファロー, IEEE 802.11g, だいたい300KB/s程度)&lt;/li&gt;&lt;li&gt;自宅の回線（AirMac Extreme, IEEE 802.11n, だいたい1MB/s程度)&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■結果&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;会社の回線・・・ダウンロードに12分~15分程度&lt;br /&gt;自宅の回線・・・ダウンロードに1分前後、インストール完了まで2分ちょっと&lt;br /&gt;&lt;br /&gt;それぞれ別の日に計測したので何とも言えませんし、会社の回線は自分以外の人も使うので遅いときがあるのですが、およそ&lt;br /&gt;&lt;br /&gt;遅いとき・・・20KB/s程度&lt;br /&gt;早いとき・・・300KB/s程度&lt;br /&gt;&lt;br /&gt;とまぁずいぶん幅がある結果になってしまいました。どうやら時間帯や相手のサーバー側の混雑具合によっても速度が違ってくるようです。いずれにせよそんな猛烈に速いわけではないので注意が必要そうです。たとえば100MBぐらいあるゲームアプリをテストしたいときなどは、今まで通りの地味な配布のほうがよい・・・ということもあるかも。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■余談：TestFlightってどれぐらいのファイルサイズまでアップロードできるのか？&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;と思って調べてみたらありました。500MBだそうです。400MBのファイルを実際にアップした人がいるみたいです。&lt;br /&gt;&lt;a href="http://support.testflightapp.com/discussions/questions/60-max-file-size-on-build-upload"&gt;http://support.testflightapp.com/discussions/questions/60-max-file-size-on-build-upload&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-6480269097389308163?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/6480269097389308163/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=6480269097389308163' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/6480269097389308163'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/6480269097389308163'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/02/testflight-no.html' title='TestFlight 経由のアプリのダウンロード速度を調べてみた'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_9HdIXu4872o/TUwYOWwMUxI/AAAAAAAACjU/5xsyP2wQoe4/s72-c/TestFlight%2BLogo.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-8809541469852985069</id><published>2011-02-02T00:17:00.003+09:00</published><updated>2011-02-02T00:28:18.281+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iPhone'/><category scheme='http://www.blogger.com/atom/ns#' term='iPad'/><category scheme='http://www.blogger.com/atom/ns#' term='iOS 4.2.1'/><category scheme='http://www.blogger.com/atom/ns#' term='Xcode 3.2.5'/><category scheme='http://www.blogger.com/atom/ns#' term='エラー'/><title type='text'>"Failed to launch simulated application: Unknown error." が発生したときの対処法</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_9HdIXu4872o/TUgmJXvdiSI/AAAAAAAACjI/S2eBA5IToM0/s1600/donotusesuchname.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 305px; height: 233px;" src="http://1.bp.blogspot.com/_9HdIXu4872o/TUgmJXvdiSI/AAAAAAAACjI/S2eBA5IToM0/s400/donotusesuchname.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5568742881677379874" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;iPhone シミュレーター起動時に表題のエラーが発生したときの対処法です。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;表題のエラーは文字通り原因不明の問題が発生したときに表示されるのですが、問題のうちの一つに「バンドルリソース内にMac OSが使用する予約されたリソース名が含まれていると発生する」というものがあります。&lt;br /&gt;&lt;br /&gt;たとえば&lt;pre&gt;Contents&lt;br /&gt;Resources&lt;/pre&gt;などの名前のディレクトリやファイルをバンドルリソース内に作成してしまうと、ビルドは通るのですがシミュレーター実行時にエラーが発生するようです。これらの予約された名前は使わないようにすると良いです。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-8809541469852985069?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/8809541469852985069/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=8809541469852985069' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/8809541469852985069'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/8809541469852985069'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/02/failed-to-launch-simulated-application.html' title='&quot;Failed to launch simulated application: Unknown error.&quot; が発生したときの対処法'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_9HdIXu4872o/TUgmJXvdiSI/AAAAAAAACjI/S2eBA5IToM0/s72-c/donotusesuchname.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-517077754533949037</id><published>2011-02-01T23:40:00.007+09:00</published><updated>2011-05-29T20:07:00.014+09:00</updated><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='iPad'/><category scheme='http://www.blogger.com/atom/ns#' term='スタイラス'/><category scheme='http://www.blogger.com/atom/ns#' term='アプリケーション'/><title type='text'>iPhone iPad 向けスタイラスで書き味勝負をしてみた</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_9HdIXu4872o/TUgbqU0fBsI/AAAAAAAACio/ihs9c-i2YzQ/s1600/Styluses.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 299px;" src="http://3.bp.blogspot.com/_9HdIXu4872o/TUgbqU0fBsI/AAAAAAAACio/ihs9c-i2YzQ/s400/Styluses.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5568731353200920258" /&gt;&lt;/a&gt;&lt;br /&gt;写真は上から順に、 &lt;a href="http://www.amazon.co.jp/%E3%83%91%E3%83%AF%E3%83%BC%E3%82%B5%E3%83%9D%E3%83%BC%E3%83%88-PBJ-91-%E3%82%B9%E3%83%9E%E3%83%BC%E3%83%88%E3%83%9A%E3%83%B3-%E3%82%B7%E3%83%AB%E3%83%90%E3%83%BC/dp/B004I8X4O4%3FSubscriptionId%3D15SMZCTB9V8NGR2TW082%26tag%3Dakisutesama-22%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3DB004I8X4O4" target="_blank"&gt;パワーサポート スマートペン PBJ-9Xシリーズ&lt;/a&gt; 、 &lt;a href="http://tenonedesign.com/sketch.php"&gt;Pogo Sketch&lt;/a&gt; 、 &lt;a href="http://ostylus.com"&gt;oStylus 初期限定生産型&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;2回戦の記事はこちら: &lt;a href="http://akisute.com/2011/05/iphone-ipad-2.html"&gt;http://akisute.com/2011/05/iphone-ipad-2.html&lt;/a&gt;&lt;br /&gt;おすすめスタイラスまとめ記事はこちら: &lt;a href="http://akisute.com/2010/06/ipad.html"&gt;http://akisute.com/2010/06/ipad.html&lt;/a&gt;&lt;br /&gt;Bamboo Stylusのレビューはこちら: &lt;a href="http://akisute.com/2011/05/ipad-bamboo-stylus.html"&gt;http://akisute.com/2011/05/ipad-bamboo-stylus.html&lt;/a&gt;&lt;br /&gt;oStylusのレビューはこちら: &lt;a href="http://akisute.com/2010/10/ipad-ostylus.html"&gt;http://akisute.com/2010/10/ipad-ostylus.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;このたび自分が納得できる完成度の iPad 向けスタイラスが3種類揃ったのを機会に、ちょっと書きくらべをしてみる事にしました。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■さっそく試してみた&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;以下、実際に手書きで字を書いてみたスクリーンショットを貼り付けます。全て一発勝負で書いています。それぞれ上からスマートペン、Pogo Sketch、oStylusです。&lt;br /&gt;&lt;br /&gt;neu.Notes&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_9HdIXu4872o/TUgbqndUxZI/AAAAAAAACiw/BI5gHYM5y9o/s1600/Styluses_neunotes.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 300px;" src="http://1.bp.blogspot.com/_9HdIXu4872o/TUgbqndUxZI/AAAAAAAACiw/BI5gHYM5y9o/s400/Styluses_neunotes.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5568731358204052882" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Penultimate&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_9HdIXu4872o/TUgbq03zFkI/AAAAAAAACi4/e3_2UrjK5Qc/s1600/Styluses_penultimate_1.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 300px; height: 400px;" src="http://1.bp.blogspot.com/_9HdIXu4872o/TUgbq03zFkI/AAAAAAAACi4/e3_2UrjK5Qc/s400/Styluses_penultimate_1.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5568731361804752450" /&gt;&lt;/a&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_9HdIXu4872o/TUgbq1Xq0sI/AAAAAAAACjA/Z5WyDxBs4OY/s1600/Styluses_penultimate_2.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 300px; height: 400px;" src="http://4.bp.blogspot.com/_9HdIXu4872o/TUgbq1Xq0sI/AAAAAAAACjA/Z5WyDxBs4OY/s400/Styluses_penultimate_2.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5568731361938428610" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■考察&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;スマートペンは本当にまるで普通のペンで紙に書いているように書けます。特に「返」のしんにょうあたりを見るとよくわかるのですが、このような綺麗な曲線が非常に楽に書けます。ただしやや太いためか細かい筆跡が難しいです。&lt;br /&gt;&lt;br /&gt;Pogo Sketchはスマートペンより細く、やや滑りが悪いため細かい線に強いですし、曲線もしなやかです。しかしながらよく見ると所々線が途切れていたり短かったりすることがわかると思います。これはタッチの感度が悪いためで、タッチを認識せず線が途切れてしまっているためこのようになってしまっています。&lt;br /&gt;&lt;br /&gt;oStylusは感度の良い金属製のペン先とペン先が見えるOリング構造のおかげで、細かい字に圧倒的な強さを誇ります。Pogo Sketchのように感度が足りず線が途切れることもありません。弱点として、全体的に長く重くペン先が平たいため、普通のペンと同じようには書けず、線が直線的になってしまっています。&lt;br /&gt;&lt;br /&gt;一番書くのが楽だったのはスマートペン、書くのに時間がかかっているのはoStylusだったと思います。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■まとめ&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;それぞれ一長一短、特徴ある iPad / iPhone 向けのスタイラスが市場に出回るようになってきて、すごくわくわくする感じです！つい1年2年前まではろくな商品がないと嘆いていたのですが、いまや自分の書きたい物に応じてスタイラスを選ぶことさえできるようになりました。素敵！&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-517077754533949037?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/517077754533949037/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=517077754533949037' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/517077754533949037'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/517077754533949037'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/02/iphone-ipad.html' title='iPhone iPad 向けスタイラスで書き味勝負をしてみた'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_9HdIXu4872o/TUgbqU0fBsI/AAAAAAAACio/ihs9c-i2YzQ/s72-c/Styluses.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-4844545138089098072</id><published>2011-01-09T00:29:00.004+09:00</published><updated>2011-01-09T01:08:22.707+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='チュートリアル'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Python で 5 分でちょっとした XML ファイルを生成する</title><content type='html'>&lt;a href="http://d.hatena.ne.jp/nishiohirokazu/20110101/1293870288"&gt;なんだか西尾先生が面白そうなことをしてるので&lt;/a&gt;、便乗してみることにしました。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■課題&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;今お仕事で iOS のアプリを書いているのですが、その中で次のような plist ファイルを作成する必要が出てきました。 plist ってのをご存じない方は、要するに XML ファイルだと思ってください。&lt;pre&gt;    &amp;lt;dict&amp;gt;&lt;br /&gt;     &amp;lt;key&amp;gt;emojiName&amp;lt;/key&amp;gt;&lt;br /&gt;     &amp;lt;string&amp;gt;&amp;#x8868;&amp;#x60C5;(&amp;#x5B09;&amp;#x3057;&amp;#x3044;)&amp;lt;/string&amp;gt;&lt;br /&gt;     &amp;lt;key&amp;gt;emojiCode&amp;lt;/key&amp;gt;&lt;br /&gt;     &amp;lt;string&amp;gt;0xE415&amp;lt;/string&amp;gt;&lt;br /&gt;    &amp;lt;/dict&amp;gt;&lt;br /&gt;    &amp;lt;dict&amp;gt;&lt;br /&gt;     &amp;lt;key&amp;gt;emojiName&amp;lt;/key&amp;gt;&lt;br /&gt;     &amp;lt;string&amp;gt;&amp;#x8868;&amp;#x60C5;(&amp;#x306B;&amp;#x3053;&amp;#x306B;&amp;#x3053;)&amp;lt;/string&amp;gt;&lt;br /&gt;     &amp;lt;key&amp;gt;emojiCode&amp;lt;/key&amp;gt;&lt;br /&gt;     &amp;lt;string&amp;gt;0xE056&amp;lt;/string&amp;gt;&lt;br /&gt;    &amp;lt;/dict&amp;gt;&lt;br /&gt;    &amp;lt;dict&amp;gt;&lt;br /&gt;     &amp;lt;key&amp;gt;emojiName&amp;lt;/key&amp;gt;&lt;br /&gt;     &amp;lt;string&amp;gt;&amp;#x8868;&amp;#x60C5;(&amp;#x7B11;&amp;#x9854;)&amp;lt;/string&amp;gt;&lt;br /&gt;     &amp;lt;key&amp;gt;emojiCode&amp;lt;/key&amp;gt;&lt;br /&gt;     &amp;lt;string&amp;gt;0xE057&amp;lt;/string&amp;gt;&lt;br /&gt;    &amp;lt;/dict&amp;gt;&lt;/pre&gt;こんな感じで全部で400項目ぐらい。Webページの資料があるので、そこから転載して上記のような plist にするお仕事です。&lt;br /&gt;&lt;br /&gt;私がやってもいいのですが、あいにく手が回りません。そこで&lt;a href="https://twitter.com/hydden0310"&gt;最近弊社に入社してきました新人さん&lt;/a&gt;にお願いすることにしました。ところがどっこい、本当に一個ずつ手で書いているからなかなか作業が進みません。ほかのお仕事もあるのですが、二日でやっと5分の1程度。これはどげんかせんといかんですね。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■さっそくやってみよう&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;まずは下準備として、ExcelにWebページから情報を貼り付けて整理します。Excelを中間エディタとして使うことで、行と列の操作が簡単になりますし、そのままコピペするだけできれいに表が完成します。整理し終わったら、Excelからテキストエディタにコピペすると、以下のような TSV (Tab Separated Value) になります。&lt;pre&gt;猫 0xE04F&lt;br /&gt;いぬ 0xE052&lt;br /&gt;ねずみ 0xE053&lt;br /&gt;うさぎ 0xE52C&lt;/pre&gt;あとはこれを XML にするだけです。さっそくPythonでやってみましょう。&lt;pre&gt;#!/usr/bin/env python&lt;br /&gt;&lt;br /&gt;data = u"""&lt;br /&gt;ここに先ほどのTSVをコピペしてください&lt;br /&gt;"""&lt;br /&gt;template = u"""&lt;br /&gt;&amp;lt;dict&amp;gt;&lt;br /&gt; &amp;lt;key&amp;gt;emojiName&amp;lt;/key&amp;gt;&lt;br /&gt; &amp;lt;string&amp;gt;%s&amp;lt;/string&amp;gt;&lt;br /&gt; &amp;lt;key&amp;gt;emojiCode&amp;lt;/key&amp;gt;&lt;br /&gt; &amp;lt;string&amp;gt;%s&amp;lt;/string&amp;gt;&lt;br /&gt;&amp;lt;/dict&amp;gt;&lt;br /&gt;"""&lt;br /&gt;&lt;br /&gt;lines = data.strip().sprit('\n')&lt;br /&gt;for line in lines:&lt;br /&gt;    t = line.sprit('\t')&lt;br /&gt;    print template % (t[0], t[1])&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;すごい原始的なコードですが、これでも十分動きますし簡単です。ってあれ、これ元ネタの西尾先生のコードとほとんど同じじゃないですか＞＜&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■その結果&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;まぁそんなこんなで無事 Python のコードもできたので動かしてみましょう。するとあっというまに目的のXMLが画面に出力されました！こうしてなんと残りの5分の4がたったの半日で終わってしまいました！単純な作業は工夫して楽に楽しく素早く片付けてしまいたいですね。&lt;br /&gt;&lt;br /&gt;そうそう、ExcelやGoogle Docsのスプレッドシートを一時作業用に使うのはおすすめです。なんだかんだで表を作るならすごく操作しやすいですし、その後作った表をテキストエディタにコピペすれば TSV が簡単に作れるので、便利です。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-4844545138089098072?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/4844545138089098072/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=4844545138089098072' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/4844545138089098072'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/4844545138089098072'/><link rel='alternate' type='text/html' href='http://akisute.com/2011/01/python-5-xml.html' title='Python で 5 分でちょっとした XML ファイルを生成する'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-7319319056409299142</id><published>2010-12-29T19:11:00.000+09:00</published><updated>2010-12-29T19:11:03.611+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iPhone'/><category scheme='http://www.blogger.com/atom/ns#' term='iPad'/><category scheme='http://www.blogger.com/atom/ns#' term='開発'/><category scheme='http://www.blogger.com/atom/ns#' term='本'/><title type='text'>はじめての iPhone 開発時にお勧めの本 3 冊</title><content type='html'>&lt;span style="font-weight:bold;"&gt;2010/12/29追加:&lt;/span&gt; 本を追加したり中身を最新のものにしたりしました。&lt;br /&gt;&lt;br /&gt;&lt;a href="http://twitter.com/monjudoh"&gt;@monjudoh&lt;/a&gt; に社内チャットで&lt;blockquote&gt;[10/09/17 17:18:12] 文 殊堂: heyあきすて&lt;br /&gt;[10/09/17 17:18:32] 文 殊堂: iPhoneアプリ開発でいい本とかある?&lt;br /&gt;[10/09/17 17:19:42] akisute: yoじゅどうもん&lt;br /&gt;[10/09/17 17:19:43] akisute: たくさんあるぜ&lt;br /&gt;[10/09/17 17:19:52] wozozo ☿: yo&lt;br /&gt;[10/09/17 17:19:53] akisute: なんかみんなから同じ質問されるからブログに書くわ&lt;/blockquote&gt;とか言われたので、お勧め本をまとめてみることにしました。2年前にも似たようなものを書いたような気がしますけど、2年が経過していますから、いろいろと状況も変化していますしね。&lt;br /&gt;&lt;br /&gt;&lt;table  border="0" cellpadding="5"&gt;&lt;tr&gt;&lt;td valign="top"&gt;&lt;a href="http://www.amazon.co.jp/%E8%A9%B3%E8%A7%A3-Objective-C-2-0-%E6%94%B9%E8%A8%82%E7%89%88-%E8%8D%BB%E5%8E%9F/dp/4797361786%3FSubscriptionId%3D15SMZCTB9V8NGR2TW082%26tag%3Dakisutesama-22%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D4797361786" target="_blank"&gt;&lt;img src="http://ecx.images-amazon.com/images/I/41aYUviRN3L._SL160_.jpg" border="0" alt="4797361786" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;font size="-1"&gt;&lt;a href="http://www.amazon.co.jp/%E8%A9%B3%E8%A7%A3-Objective-C-2-0-%E6%94%B9%E8%A8%82%E7%89%88-%E8%8D%BB%E5%8E%9F/dp/4797361786%3FSubscriptionId%3D15SMZCTB9V8NGR2TW082%26tag%3Dakisutesama-22%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D4797361786" target="_blank"&gt;詳解 Objective-C 2.0 改訂版&lt;/a&gt;&lt;img src="http://www.assoc-amazon.jp/e/ir?t=akisutesama-22&amp;l=ur2&amp;o=9" width="1" height="1" style="border: none;" alt="" /&gt;&lt;br /&gt;荻原 剛志 &lt;br /&gt;ソフトバンククリエイティブ  2010-12-17&lt;br /&gt;&lt;br /&gt;&lt;/font&gt;&lt;font size="-2"&gt;by &lt;a href="http://www.goodpic.com/mt/aws/index.html" &gt;G-Tools&lt;/a&gt;&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;2年前にも詳解しましたがこいつはバイブルです。改訂版になってBlockがらみの記述が増えたり、iOSについての言及が増えて、さらに良書になりました。四の五の言わずに買っておくと良いです。ただし、どちらかというとObjective-Cに焦点を置いている本であり、iOSで何ができるか、ということについてはほとんど記載がないので注意してください。&lt;br /&gt;&lt;br /&gt;&lt;table  border="0" cellpadding="5"&gt;&lt;tr&gt;&lt;td valign="top"&gt;&lt;a href="http://www.amazon.co.jp/%E3%81%AF%E3%81%98%E3%82%81%E3%81%A6%E3%81%AEiPhone3%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-Dave-Mark/dp/4797358106%3FSubscriptionId%3D15SMZCTB9V8NGR2TW082%26tag%3Dakisutesama-22%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D4797358106" target="_blank"&gt;&lt;img src="http://ecx.images-amazon.com/images/I/51Xh3SHkBaL._SL160_.jpg" border="0" alt="4797358106" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;font size="-1"&gt;&lt;a href="http://www.amazon.co.jp/%E3%81%AF%E3%81%98%E3%82%81%E3%81%A6%E3%81%AEiPhone3%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-Dave-Mark/dp/4797358106%3FSubscriptionId%3D15SMZCTB9V8NGR2TW082%26tag%3Dakisutesama-22%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D4797358106" target="_blank"&gt;はじめてのiPhone3プログラミング&lt;/a&gt;&lt;img src="http://www.assoc-amazon.jp/e/ir?t=akisutesama-22&amp;l=ur2&amp;o=9" width="1" height="1" style="border: none;" alt="" /&gt;&lt;br /&gt;Dave Mark Jeff LaMarche 鮎川 不二雄 &lt;br /&gt;ソフトバンククリエイティブ  2009-12-17&lt;br /&gt;&lt;br /&gt;&lt;/font&gt;&lt;font size="-2"&gt;by &lt;a href="http://www.goodpic.com/mt/aws/index.html" &gt;G-Tools&lt;/a&gt;&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;こちらは iOS のバイブルです。初めて挑戦する人に最適ですが、ある程度熟練した人が見ても発見がある良書です。およそ必要なことはすべて得られると思います。&lt;br /&gt;&lt;br /&gt;&lt;table  border="0" cellpadding="5"&gt;&lt;tr&gt;&lt;td valign="top"&gt;&lt;a href="http://www.amazon.co.jp/iPhone%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0UIKit%E8%A9%B3%E8%A7%A3%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9-%E6%89%80-%E5%8F%8B%E5%A4%AA/dp/4897978440%3FSubscriptionId%3D15SMZCTB9V8NGR2TW082%26tag%3Dakisutesama-22%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D4897978440" target="_blank"&gt;&lt;img src="http://ecx.images-amazon.com/images/I/51S0mLDifhL._SL160_.jpg" border="0" alt="4897978440" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;font size="-1"&gt;&lt;a href="http://www.amazon.co.jp/iPhone%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0UIKit%E8%A9%B3%E8%A7%A3%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9-%E6%89%80-%E5%8F%8B%E5%A4%AA/dp/4897978440%3FSubscriptionId%3D15SMZCTB9V8NGR2TW082%26tag%3Dakisutesama-22%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D4897978440" target="_blank"&gt;iPhoneプログラミングUIKit詳解リファレンス&lt;/a&gt;&lt;img src="http://www.assoc-amazon.jp/e/ir?t=akisutesama-22&amp;l=ur2&amp;o=9" width="1" height="1" style="border: none;" alt="" /&gt;&lt;br /&gt;所 友太 京セラコミュニケーションシステム株式会社 &lt;br /&gt;リックテレコム  2010-01-12&lt;br /&gt;&lt;br /&gt;&lt;/font&gt;&lt;font size="-2"&gt;by &lt;a href="http://www.goodpic.com/mt/aws/index.html" &gt;G-Tools&lt;/a&gt;&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;UIKitに焦点を置いて書かれている本です。図解が多く、全くiOS開発をしたことがない人でもどのようなUI要素が使えるのか見て学べるため大変おすすめです。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-7319319056409299142?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/7319319056409299142/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=7319319056409299142' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/7319319056409299142'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/7319319056409299142'/><link rel='alternate' type='text/html' href='http://akisute.com/2010/09/iphone-2.html' title='はじめての iPhone 開発時にお勧めの本 3 冊'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-4870118014875201198</id><published>2010-12-29T18:43:00.006+09:00</published><updated>2010-12-29T19:18:44.415+09:00</updated><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='iPad'/><category scheme='http://www.blogger.com/atom/ns#' term='ソースコード'/><category scheme='http://www.blogger.com/atom/ns#' term='iOS 4.2.1'/><title type='text'>ASIHTTPRequest を使って外部 API から非同期的に結果を取得してみる</title><content type='html'>&lt;a href="http://allseeing-i.com/ASIHTTPRequest/"&gt;ASIHTTPRequest&lt;/a&gt; という神の通信ライブラリを使って、うまい具合に外部 API から非同期的に結果を取得・解析して返すようなクラスをつくってみました。以前 NSOperation でやってみたバージョンは &lt;a href="http://akisute.com/2010/06/nsoperation-api.html"&gt;こちら。&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■主な機能&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;元々の ASIHTTPRequest にある機能はもちろんご利用いただけます。多すぎて説明し切れませんので、以下の記事を参考にしていただければと思います＞＜&lt;br /&gt;&lt;br /&gt;&lt;a href="http://d.hatena.ne.jp/ninjinkun/20101122/1290394265"&gt;http://d.hatena.ne.jp/ninjinkun/20101122/1290394265&lt;/a&gt;&lt;br /&gt;&lt;a href="http://macisv.jp/blog/?p=235"&gt;http://macisv.jp/blog/?p=235&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;さらに今回私が作成した ASIAPIRequest にはこのようなおいしい特典がつきました。&lt;ul&gt;&lt;li&gt;POST のパラメータだけではなく、 GET のパラメータも楽々生成してくれるメソッドを用意しました。&lt;/li&gt;&lt;li&gt;非同期実行時の通知方法が, delegate, blockに加え、さらに NSNotification による通知もサポートしました。&lt;/li&gt;&lt;li&gt;非同期的に取得したレスポンスの値をパースするためのコールバックを用意しました。このコールバックメソッドをオーバーライドして、サブクラスで処理を行えば、この中の処理はすべて非同期実行されるため、 XML のパースが遅くて UI が固まったなんてことはもうありません。&lt;/li&gt;&lt;li&gt;おまけ的にタグとかつけられるようにしてみました。&lt;/li&gt;&lt;/ul&gt;その他、お使いになられる際に適当に ASIAPIRequest の中身を書き換え御社のプロジェクトに合うように調整するなどすると面白いと思います。自動的にログインパラメータをつけるようにしたりとか。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■ダウンロード&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;github にリポジトリを作りましたので、こちらから git でクローンするか、または master のソースコードをダウンロードしてください。&lt;br /&gt;&lt;br /&gt;&lt;a href="https://github.com/akisute/asi-http-request"&gt;https://github.com/akisute/asi-http-request&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;タグが付与されていますが、これはクローン元のタグなので、当てにしないでください。常に master の先端をダウンロードするのが一番確実です。&lt;br /&gt;&lt;br /&gt;ダウンロードしたら、 Classes ディレクトリと External ディレクトリの中身を適当に自分のプロジェクトにコピーして、プロジェクトに追加していただければOKです。最後に、以下のフレームワークをリンクしてください。&lt;ul&gt;&lt;li&gt;CFNetwork&lt;/li&gt;&lt;li&gt;SystemConfiguration&lt;/li&gt;&lt;li&gt;MobileCoreServices&lt;/li&gt;&lt;li&gt;CoreGraphics&lt;/li&gt;&lt;li&gt;zlib&lt;/li&gt;&lt;/ul&gt;ライセンスは元のライブラリに合わせて BSD ライセンスとします。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■使い方&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;最初に ASIAPIRequest を継承してサブクラスを作成します。&lt;pre&gt;// APIAuthorize.h&lt;br /&gt;&lt;br /&gt;@interface APIAuthorize : ASIAPIRequest {&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// 認証APIのインスタンスを生成する&lt;br /&gt;+ (id)apiWithUserId:(NSString :)userId password:(NSString :)password;&lt;br /&gt;&lt;br /&gt;@end&lt;/pre&gt;では次にAPIインスタンスを生成するためのクラスメソッドをサブクラスの内部に作ってみましょう。&lt;pre&gt;// APIAuthorize.m&lt;br /&gt;&lt;br /&gt;+ (id)apiWithUserId:(NSString :)userId password:(NSString :)password {&lt;br /&gt;    NSURL *url = [NSURL URLWithString:@"authorize.json" relativeToURL:API_BASE_URL_STRING];&lt;br /&gt;    APIAuthorize *api = [APIAuthorize requestWithURL:url];&lt;br /&gt;    api.requestMethod = @"POST";&lt;br /&gt;    [api setPostValue:userId forKey:@"userId"];&lt;br /&gt;    [api setPostValue:password forKey:@"password"];&lt;br /&gt;    api.postRequestFinishedNotificationName = @"APIAuthorizeDidFinishNotification"; // POST 成功時に飛ぶnotificationの名前&lt;br /&gt;    api.postRequestFailedNotificationName = @"APIAuthorizeDidFailNotification";     // POST 失敗時に飛ぶnotificationの名前&lt;br /&gt;    return api;&lt;br /&gt;}&lt;/pre&gt;最後にサブクラス内部でスーパークラスのメソッドをオーバーライドし、通信完了直後に呼び出される処理を記述します。たとえば、レスポンスが返ってきた際に、受け取ったレスポンスをパースして DB に保存したりします。このコールバック内部は UI スレッドとは別のスレッドで並列実行されているので、この中でどれだけ重い処理をしても UI は固まりません。その代わり UI を操作する処理はここでは行わないでください。クラッシュします。&lt;pre&gt;// APIAuthorize.m&lt;br /&gt;&lt;br /&gt;- (void)postRequestFinished {&lt;br /&gt;    // レスポンスステータスコードが異常系の場合はなにもしない&lt;br /&gt;    if (self.responseStatusCode != 200) {&lt;br /&gt;        return;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // レスポンスをパースしてオブジェクトにし、Core Dataに保存する&lt;br /&gt;    // 保存したオブジェクトをuserInfoに格納しておく&lt;br /&gt;    User *user = [User managedObjectFromJsonString:[self responseString]&lt;br /&gt;                                         inContext:[AppDelegate appDelegate].managedObjectContext];&lt;br /&gt;    [[AppDelegate appDelegate].managedObjectContext save:nil];&lt;br /&gt;    self.userInfo = [NSDictionary dictionaryWithObjectsAndKeys:&lt;br /&gt;                     user, @"user",&lt;br /&gt;                     nil];&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;- (void)postRequestFailedWithError:(NSError *)theError {&lt;br /&gt;    // なにもしない&lt;br /&gt;}&lt;/pre&gt;tag プロパティを使って、同じAPIでレスポンスの種類を分けることができたりします。&lt;pre&gt;// APIAuthorize.m&lt;br /&gt;&lt;br /&gt;enum {&lt;br /&gt;    APIAuthorizeResponseTagUser,&lt;br /&gt;    APIAuthroizeResponseTagToken,&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;+ (id)apiWithUserId:(NSString :)userId password:(NSString :)password {&lt;br /&gt;    NSURL *url = [NSURL URLWithString:@"authorize.json" relativeToURL:API_BASE_URL_STRING];&lt;br /&gt;    APIAuthorize *api = [APIAuthorize requestWithURL:url];&lt;br /&gt;    api.requestMethod = @"POST";&lt;br /&gt;    [api setPostValue:userId forKey:@"userId"];&lt;br /&gt;    [api setPostValue:password forKey:@"password"];&lt;br /&gt;    api.postRequestFinishedNotificationName = @"APIAuthorizeDidFinishNotification"; // POST 成功時に飛ぶnotificationの名前&lt;br /&gt;    api.postRequestFailedNotificationName = @"APIAuthorizeDidFailNotification";     // POST 失敗時に飛ぶnotificationの名前&lt;br /&gt;    api.tag = APIAuthorizeResponseTagUser                                           // このAPIのレスポンスはUser型だよーとタグをつけておく&lt;br /&gt;    return api;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;- (void)postRequestFinished {&lt;br /&gt;    switch (self.tag) {&lt;br /&gt;        case APIAuthorizeResponseTagUser:&lt;br /&gt;          // Userオブジェクトを作る&lt;br /&gt;          break;&lt;br /&gt;        case APIAuthroizeResponseTagToken:&lt;br /&gt;          // Tokenオブジェクトを作る&lt;br /&gt;          break;&lt;br /&gt;        default:&lt;br /&gt;          break;&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;これで API 本体は完成したので、早速実行してみましょう。以下の4つの方法で実行が可能です。&lt;ol&gt;&lt;li&gt;同期実行&lt;/li&gt;&lt;li&gt;非同期実行、 delegate で結果を通知してもらう&lt;/li&gt;&lt;li&gt;非同期実行、 NSBlock で通信完了後の処理を行う&lt;/li&gt;&lt;li&gt;非同期実行、 NSNotification で結果を通知してもらう&lt;/li&gt;&lt;/ol&gt;1, 2, 3 については普通の ASIHTTPRequest と同じですので割愛します。 4 は私が新しく追加した機能で、 NSNotification の仕組みを使って実行完了通知を受け取ることが可能になります。たとえばこんな感じになります。&lt;pre&gt;// 適当に認証とかする画面のViewController.m&lt;br /&gt;&lt;br /&gt;- (void)viewWillAppear:(BOOL)animated {&lt;br /&gt;    [super viewWillAppear:animated];&lt;br /&gt;    // Notification通知を開始する&lt;br /&gt;    [[NSNotificationCenter defaultCenter] addObserver:self&lt;br /&gt;                                                 name:@"APIAuthorizeDidFinishNotification" // さっき決めた文字列&lt;br /&gt;                                               target:self&lt;br /&gt;                                               action:@selector(apiAuthorizeDidFinish:)&lt;br /&gt;                                               object:nil];&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;- (void)viewDidDisappear:(BOOL)animated {&lt;br /&gt;    [super viewDidDisappear:animated];&lt;br /&gt;    // Notification通知をオフにする&lt;br /&gt;    [[NSNotificationCenter defaultCenter] removeObserver:self];&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;- (IBAction)startAuthorize {&lt;br /&gt;    ASIAPIRequest *api = [APIAuthorize apiWithUserId:self.userIdField.text password:self.passwordField.text];&lt;br /&gt;    [api startAsynchronomus];&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;- (void)apiAuthorizeDidFinish:(NSNotification *)notification {&lt;br /&gt;      // 認証完了時の処理&lt;br /&gt;}&lt;/pre&gt;この通知はメインスレッドから呼び出されるので、自由に UI を操作することが可能です。&lt;br /&gt;&lt;br /&gt;delegate と比べて、 NSNotification を使った通知の便利な点は以下の通り。&lt;ul&gt;&lt;li&gt;delegate を使う場合には、 delegate オブジェクトがメモリから消える前に delegate の始末を行う必要があるが、 NSNotification を使った場合にはその必要がない。自分を NSNotificationCenter から削除するだけでよいので、 API リクエストを比較的投げっぱなしにできる。&lt;/li&gt;&lt;li&gt;delegate とは違い、複数のオブジェクトで同時に通知を受け取ることができる。たとえば API を実行した画面とは全然違う別の画面二つで同時に通知を受け取ったりすることが可能になる。&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■余談&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;この ASIHTTPRequest は本当にすばらしいです。最初にこの通信ライブラリを知ったときは、また良くあるただのちょっと便利なだけな通信ライブラリなんだろうと思い気にもとめなかったのですが、実際にコードを見てびっくりしました。私がほしかった通信ライブラリそのものだったからです。&lt;br /&gt;&lt;br /&gt;私は通信ライブラリは NSOperation を継承して作るべきだと考えており、実際以前に試してみたことがありました。それは主に、&lt;ul&gt;&lt;li&gt;NSOperationQueue のシングルトンインスタンスが勝手に通信をすべて管理してくれるので、クラスの変数として通信クラスのインスタンスを保持しておかなくても良くなるかもしれない&lt;/li&gt;&lt;li&gt;NSOperation には依存関係を指定するメソッドがあるので、これを用いれば自動的に通信 A, B, C を順序通りに実行するなどできるかもしれない&lt;/li&gt;&lt;li&gt;NSOperation を継承すれば、将来 Apple の中の人がフレームワークを改善した際にマルチコア化した iPhone の CPU の恩恵を自動的に受けられるかもしれない&lt;/li&gt;&lt;/ul&gt;という考えがあったからです。そしたら見事にこの ASIHTTPRequest が NSOperation を継承して、しかも何かと問題の多い NSURLConnection を使わず NSStream とソケットを用いて自分で Run Loop を回すというすばらしい実装をしているじゃないですか！こりゃもうかないません。自分でやる必要が丸でなくなってしまいました。しかもそれだけではなく、&lt;ul&gt;&lt;li&gt;現在全体の何%まで読み込みが完了したかを delegate で通知できる&lt;/li&gt;&lt;li&gt;通信完了時に呼び出される delegate method はすべて main thread から呼び出されるので、 UI 操作をしても安全&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/42067579805640535-4870118014875201198?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/4870118014875201198/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=4870118014875201198' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/4870118014875201198'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/4870118014875201198'/><link rel='alternate' type='text/html' href='http://akisute.com/2010/12/asihttprequest-api.html' title='ASIHTTPRequest を使って外部 API から非同期的に結果を取得してみる'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-8885578684220363177</id><published>2010-12-29T13:47:00.003+09:00</published><updated>2010-12-29T13:50:51.778+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iPhone'/><category scheme='http://www.blogger.com/atom/ns#' term='iPad'/><category scheme='http://www.blogger.com/atom/ns#' term='Xcode'/><category scheme='http://www.blogger.com/atom/ns#' term='エラー'/><category scheme='http://www.blogger.com/atom/ns#' term='設定'/><title type='text'>アプリのビルド時に CSSMERR_TP_NOT_TRUSTED エラーが発生したときの対処法</title><content type='html'>&lt;a href="http://d.hatena.ne.jp/drill256/20090820/1250752178"&gt;http://d.hatena.ne.jp/drill256/20090820/1250752178&lt;/a&gt;&lt;br /&gt;&lt;a href="http://discussions.apple.com/thread.jspa?threadID=1630090"&gt;http://discussions.apple.com/thread.jspa?threadID=1630090&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;このエラーは、以下の証明書がすべて存在しないか、または Keychain Access 内でのステータスが、「この証明書は信頼されています。」ではないときに発生するようです。&lt;ul&gt;&lt;li&gt;Apple Worldwide Developer Relations Certification Authority&lt;/li&gt;&lt;li&gt;iPhone Developer または iPhone Distribution&lt;/li&gt;&lt;/ul&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_9HdIXu4872o/TRq9ojQcOiI/AAAAAAAACig/NWgXjJ_sYiw/s1600/iPhoneDevCert.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 259px;" src="http://3.bp.blogspot.com/_9HdIXu4872o/TRq9ojQcOiI/AAAAAAAACig/NWgXjJ_sYiw/s400/iPhoneDevCert.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5555961594671544866" /&gt;&lt;/a&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_9HdIXu4872o/TRq9oH1rl0I/AAAAAAAACiY/ZjBx-0YXPKs/s1600/AppleWWDRCert.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 259px;" src="http://4.bp.blogspot.com/_9HdIXu4872o/TRq9oH1rl0I/AAAAAAAACiY/ZjBx-0YXPKs/s400/AppleWWDRCert.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5555961587311548226" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;上記の画像のように、「この証明書は信頼されています。」と緑色のチェックマーク付きで表示されている必要があります。そうでない場合は何らかの問題があります。&lt;br /&gt;&lt;br /&gt;対処法は、&lt;ol&gt;&lt;li&gt;まず何はなくともこれらの証明書がすべて存在するか確認する。 Apple Worldwide Developer Relations Certification Authority を忘れているケースが良くあります。&lt;/li&gt;&lt;li&gt;「この証明書は信頼されています。」になっていない場合には、証明書を選択して、「情報を見る」 -&gt; 「信頼」 -&gt; 「システムデフォルトを使う」 を選択する。「常に信頼する」ではダメです、エラーになります。&lt;/li&gt;&lt;/ol&gt;証明書をどのキーチェイン項目に入れていても問題はなさそうです。私の場合は WWDR をシステムに、　iPhone Developer をログインに入れていますが正常に動作しています。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-8885578684220363177?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/8885578684220363177/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=8885578684220363177' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/8885578684220363177'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/8885578684220363177'/><link rel='alternate' type='text/html' href='http://akisute.com/2010/12/cssmerrtpnottrusted.html' title='アプリのビルド時に CSSMERR_TP_NOT_TRUSTED エラーが発生したときの対処法'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_9HdIXu4872o/TRq9ojQcOiI/AAAAAAAACig/NWgXjJ_sYiw/s72-c/iPhoneDevCert.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-1920109605272401186</id><published>2010-11-16T22:16:00.005+09:00</published><updated>2010-11-16T22:37:44.812+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iPhone OS 3.0'/><category scheme='http://www.blogger.com/atom/ns#' term='iOS 4.0'/><category scheme='http://www.blogger.com/atom/ns#' term='Cocoa'/><category scheme='http://www.blogger.com/atom/ns#' term='開発'/><category scheme='http://www.blogger.com/atom/ns#' term='iPhone OS 3.2'/><title type='text'>iOS で正規表現を使う (3.0, 3.1, 3.2, 4.0)</title><content type='html'>iPhone / iPad アプリで正規表現を使いたいときはどうするのか調べてみました。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■iOS 4.0以上&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;NSRegularExpression があるのでそれを使えば万事解決です。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■iOS 3.2&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://blog.livedoor.jp/pnfhy316/archives/277806.html"&gt;http://blog.livedoor.jp/pnfhy316/archives/277806.html&lt;/a&gt;&lt;br /&gt;こちらのブログでご紹介されているとおり、NSString rangeOfString:options: で NSRegularExpressionSearch を指定するのが楽です。&lt;br /&gt;&lt;br /&gt;正規表現のグループ参照はできませんけれど、まぁしょうがないですかね。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■iOS 3.1, 3.0&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://d.hatena.ne.jp/KishikawaKatsumi/20081031/1225463896"&gt;http://d.hatena.ne.jp/KishikawaKatsumi/20081031/1225463896&lt;/a&gt;&lt;br /&gt;こちらのブログでご紹介されているとおり、ライブラリを使うのがよいようです。&lt;br /&gt;&lt;br /&gt;または最近調べてわかったのですが、 NSPredicate を以下のように使うと正規表現によるマッチングが可能になる模様です。&lt;pre&gt;NSString *path = @"/path/to/img/img10001.png";&lt;br /&gt;NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%@ matches '.*/img[0-9]{5}\\.png'", path];&lt;br /&gt;BOOL matched = [predicate evaluateWithObject:nil];&lt;/pre&gt;キモは NSPredicate の format として matches という構文が使えることと、その中で正規表現が使用できるところですかね。実機の iOS 3.X で試したわけではないのですが、 NSPredicate 自体が iOS3.0 から使用可能になっていることと、 NSPredicate format 関連のドキュメントを見ても特に利用制限とかは書いていなかったので、普通に3.0から使えるんじゃないかと思ってます。もしよろしければ動作報告いただけるとうれしいです。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■iOS 2.X&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;iOS界のIEだと思って忘れましょう。お客さんに「頼むから対応してくれ」と言われても突っぱねる（すでに全体の1%以下ぐらいのはず）のがベストです。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-1920109605272401186?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/1920109605272401186/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=1920109605272401186' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/1920109605272401186'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/1920109605272401186'/><link rel='alternate' type='text/html' href='http://akisute.com/2010/11/ios-30-31-32-40.html' title='iOS で正規表現を使う (3.0, 3.1, 3.2, 4.0)'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-4464337054534785649</id><published>2010-11-04T16:49:00.005+09:00</published><updated>2010-11-04T17:08:03.332+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iOS 4.1'/><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='Objective-C'/><title type='text'>iPhone / iPad でIPアドレスやMACアドレスを取得するクラスを書いてみた</title><content type='html'>たまには技術ネタを書きます。 iOS で IPアドレスや MACアドレスを取得するためのObjective-Cクラスを書いてみました。&lt;br /&gt;コードはこちら。&lt;br /&gt;&lt;br /&gt;&lt;a href="https://gist.github.com/662203"&gt;https://gist.github.com/662203&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;ライセンスは記載のとおりMITライセンスです。&lt;br /&gt;&lt;br /&gt;参考にしたサイトはこちら。&lt;br /&gt;&lt;br /&gt;&lt;a href="http://stackoverflow.com/questions/677530/how-can-i-programmatically-get-the-mac-address-of-an-iphone"&gt;http://stackoverflow.com/questions/677530/how-can-i-programmatically-get-the-mac-address-of-an-iphone&lt;/a&gt;&lt;br /&gt;&lt;a href="http://iphonesdksnippets.com/post/2009/09/07/Get-IP-address-of-iPhone.aspx"&gt;http://iphonesdksnippets.com/post/2009/09/07/Get-IP-address-of-iPhone.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■ほんのちょっとだけ説明&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;BSDのioctl()関数を使いますと、デバイスのIO周りのありとあらゆる情報を取ってくる事ができます。・・・らしいです。それを使ってIPアドレスやMACアドレスを取ってみました。大本のコードは確か StackOverflow あたりにあったのですが、もろにC言語ベタベタだったので使いやすくするためObjective-Cのクラスにしています。といってもまだまだ改善点が山ほどありますので好き勝手に触りまくってください。&lt;br /&gt;&lt;br /&gt;っていうか今気づいた、二番目のサイトそのまんまほとんど同じコードじゃないですか＞＜ 別にいまさら作らなくても良かったですね。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-4464337054534785649?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/4464337054534785649/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=4464337054534785649' title='2 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/4464337054534785649'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/4464337054534785649'/><link rel='alternate' type='text/html' href='http://akisute.com/2010/11/iphone-ipad-ipmac.html' title='iPhone / iPad でIPアドレスやMACアドレスを取得するクラスを書いてみた'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-2890904573018930704</id><published>2010-10-26T00:33:00.009+09:00</published><updated>2010-10-26T00:54:33.951+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ライフハック'/><title type='text'>ゲームプログラマになりたい中学三年生のためにアドバイスを考えてみた</title><content type='html'>&lt;span style="font-weight:bold; font-size:110%;"&gt;■発端&lt;/span&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;先日誕生日だったので実家に電話した&lt;/li&gt;&lt;li&gt;おかんが出てきた&lt;/li&gt;&lt;li&gt;おかんの友人の奥様の息子さんの話になる&lt;ul&gt;&lt;li&gt;なんでやねん&lt;/li&gt;&lt;li&gt;中学３年で進学シーズンです&lt;/li&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;/ol&gt;という無茶振りを受けたのでこんな記事を書く事になりました。 &lt;a href="http://akisute.com/2010/08/iphone.html"&gt;あれ、又このパターン？&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■いきなり結論&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;ゲームプログラマーですか？ &lt;span style="font-weight:bold; color:#cc0000;"&gt;もちろんなれます。続けられるのであれば。&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;なんだか世の中には &lt;a href="http://lifehacking.jp/2008/11/the-law-of-10000-hours/"&gt;一万時間の法則&lt;/a&gt; というものがあるらしくて、一万時間ほど経験を積めば大成できるらしいです。私も身に覚えがちょっとだけあるので、この一万時間というのはあながち間違ってないのではないかと思います。リンク先の lifehacking.jp さんの記事によりますと、&lt;pre&gt;２年：10000 / (2 x 365) = 13.7 時間&lt;br /&gt;５年：10000 / (5 x 365) = 5.4 時間&lt;br /&gt;１０年：10000 / (10 x 365) = 2.7 時間&lt;/pre&gt;らしいので、こう考えることが出来ます。&lt;dl&gt;&lt;dt&gt;一日 13.7 時間、365日、一日も休むこと無くPCの前に座ってプログラムを書いていられる！&lt;/dt&gt;&lt;dd&gt;おめでとう、２年でゲームプログラマーになれます！むしろイチローにだってなれますよ！&lt;/dd&gt;&lt;dt&gt;一日 8 時間、一日も休むこと無く学校に通ってプログラムの勉強ができる！&lt;/dt&gt;&lt;dd&gt;3年間学校に通うとすれば、卒業するまで毎日やってもまだ６割程度。残りは自分で身につけるため、まだまだ勉強を続ける必要があります。&lt;/dd&gt;&lt;dt&gt;一日 2.7 時間、365日、一日も休むこと無く家に帰ってからプログラムを書いて勉強できる！&lt;/dt&gt;&lt;dd&gt;それでも10年続ける必要があります。いまあなたが15歳なら、25歳です。5歳のときの自分、覚えてますか？&lt;/dd&gt;&lt;/dl&gt;はい、相当大変だということがおわかりになるかと思います。つまりこれだけの大変なことをどうやって毎日続けるか、というのがゲームプログラマーになるキモのようです。早速次章以降で検証してみましょう。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■でもちょっとまった&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;ただちょっと思ったのが、多分彼はゲームプログラマーという仕事を勘違いされているんじゃないかと。ゲームプログラマー = ゲームを作れる人、と思われているのではないかと。実際私も中学生ぐらいの頃はそうでした。&lt;br /&gt;&lt;br /&gt;しかし現実は ゲームプログラマー = ゲームを作れる人 ではなく、 ゲームプログラマー = ゲームの一部を作れる人 です。まずこれに気づいて、この現実を受け入れることがすごく大事です。&lt;br /&gt;&lt;br /&gt;これはものすごく当たり前のことなのですが、たいてい子供時代に夢見ているゲームプログラマー像にはこれが含まれていません。実際、面白いゲームを作るには、&lt;ul&gt;&lt;li&gt;むちゃくちゃ面白いゲームのアイディア&lt;/li&gt;&lt;li&gt;超カッコイイグラフィック&lt;ul&gt;&lt;li&gt;2D&lt;/li&gt;&lt;li&gt;3D&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;爽快な音楽&lt;ul&gt;&lt;li&gt;BGM&lt;/li&gt;&lt;li&gt;効果音&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;そしてもちろんプログラミング&lt;/li&gt;&lt;/ul&gt;と、これだけの要素が必要になってしまうわけです。もちろんアイディアも絵も音楽も借りてきたりフリーの素材を使ったりできますが、すべてがすべてフリーの素材でまかなえるわけではなく（そもそもやってみるとわかるのですが、すべてフリーの素材で作ると、自分が作ったものではないように感じられ気が萎えてしまいます）、どこかはオリジナルでやらなくてはなりません。で、当然自分ひとりでこれだけの要素をまかなえるかというと 普通は無理 なわけです。もちろん &lt;a href="http://twitter.com/korindo"&gt;例外&lt;/a&gt; もいらっしゃいますが・・・とにかく、 &lt;span style="font-weight:bold; color:#cc0000;"&gt;ゲームは自分ひとりで作るものじゃないんです。&lt;/span&gt;&lt;br /&gt;&lt;br /&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;li&gt;このゲームのBGMはマジ燃える&lt;/li&gt;&lt;/ul&gt;どれもゲームを褒める言葉なのですが、なんとまぁ、どの褒め言葉も全然プログラマーが褒められてません。&lt;br /&gt;&lt;br /&gt;じゃあ何が楽しくてゲームプログラマーをやるのか？&lt;br /&gt;&lt;br /&gt;最高の自己満足です。プログラムを書くこと自体が楽しいのです。以上。&lt;br /&gt;&lt;br /&gt;さて、どうしてわざわざこのような事を書いたのかといいますと、実は彼がなりたいのはゲームプログラマーではなくてゲームに関わる仕事の何かじゃないかと思ったからなのです。単にゲームが好きで、PCを使ってゲームに関わる仕事がしたいなら、いくらでも他に道があります。絵を書いたり、音楽を作ったり、シナリオを書いたり。いろいろ試してみて、一番自分が好きになったものを極めればいいのです。ですので心あたりがあるのであれば、プログラミングと決めつけずに絵を書いたり音楽を作ったりシナリオを書いたり、ああそれより何より大事、自分以外のゲームに関わる仕事がしたい仲間を探してみたり、いろいろやってみてください。どうすればいいかわからない？私はプログラマーであって絵を書いたり音を作る方法は全然知りませんが、 &lt;a href="http://www.google.co.jp"&gt;Google先生が知っています。&lt;/a&gt; 思いつく限りGoogle先生に１００回でも２００回でも聞けばいいのです。一日 2.7 時間、365日、一日も休むこと無くプログラムを書くのに比べたら屁でもないぐらいカンタンですよね？&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■それじゃあプログラマーになろう&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;よし、これだけ脅してもまだ &lt;span style="font-weight:bold; color:#cc0000;"&gt;プログラマー最高！！&lt;/span&gt; とお考えのHENTAI諸君、ようこそ！それではさっそく１０年間続ける方法を考えます。&lt;ol&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;li&gt;入門書を読む&lt;/li&gt;&lt;/ol&gt;まず一番目。私が事あるごとに言ってますが、楽をしましょう。自分に一番あった方法を取って楽をして、そのかわり毎日続けましょう。ゲームプログラマーになりたいのだからまずはゲームプログラミングだろうと思われるかもしれませんが、実はゲームプログラミングはプログラミングの最高峰、最も難易度が高いのです。少なくともWebプログラミングや、最近流行りの iOS / Android でのプログラミングに比べれば、格段に難しく、いきなりここから入ると確実に心がバキバキ折れます。自分はガッツがあって、絶対最後までやり遂げてやると決めて最後までできる人でしたら、このいきなりゲームプログラミングから入ってゲームプログラマーになるのが最短ルートですが、私には到底不可能でした。&lt;br /&gt;&lt;br /&gt;そこで最初はまず楽しむことをおすすめします。F1レーサーだって、最初からいきなりF1マシンに乗ったりはしません。最初は普通の車やカートに乗ります。同じように、いきなり難易度激高のC言語をマスターするのではなく、楽をして楽しんで毎日続けられてしかもためになる、そんなプログラミング言語がいいですよね。いくつか私のおすすめをご紹介しましょう。&lt;dl&gt;&lt;dt&gt;Processing&lt;/dt&gt;&lt;dd&gt;本当におすすめです。ぶっちゃけこの言語だけで2Dグラフィックを使った簡単なゲームを作ることが出来ます。いちいち超面倒なrun loopの管理を自分でする必要もありません。そして使っていて面白い！ &lt;a href="http://akisute.com/2009/12/processing.html"&gt;http://akisute.com/2009/12/processing.html&lt;/a&gt; とか見ていただければ面白さが伝わるかと！Processingで何か色々作ってみて、遅いとか重いとかもっと難しいことがしたいと思ったら、DirectXとかバリバリ使ったものに挑戦すればよいのです。&lt;/dd&gt;&lt;dt&gt;Python&lt;/dt&gt;&lt;dd&gt;これは非常に地味な言語なのですが、プログラムのロジックやオブジェクト指向などを学ぶのに最適だと思ってます。なにより使っていて楽です。もっとも楽すぎてC言語に戻れなくなるかもしれませんが・・・&lt;/dd&gt;&lt;dt&gt;HSP&lt;/dt&gt;&lt;dd&gt;これも入門にはよさそうなのですが、使ったことがないのですみません、感想が出せなくて。&lt;/dd&gt;&lt;/dl&gt;さて次、二番目。ほんの僅かでもわからないことがあったら即ググれ。自分で調べる力がないと仕事でプログラムなんぞ書いていられません。しかし、自分で調べるのは大変な作業で心が折れるときもありますし、なによりGoogle先生ですらわからないことはたくさんあります。&lt;br /&gt;&lt;br /&gt;そこで三番目。エライ人と仲良くなれ。昔はそんなの絶対不可能でしたが、いまや Mixi Twitter はてな Facebook なんでもござれです。これらのサービスを使ってちょっと調べればHENTAIレベルの神プログラマの日々のつぶやきを簡単に見ることができます。テンション上がりますね。それにひょっとしたらHENTAIたちと仲良くなれるかもしれません。そうすればGoogle先生すら教えてくれない情報をお互いに交換し切磋琢磨することができるようになります。&lt;br /&gt;&lt;br /&gt;中学三年生でプログラマーといえばやっぱり &lt;a href="https://twitter.com/tehutehuapple"&gt;tefu&lt;/a&gt; 君をフォローするのがいいのかなと。&lt;br /&gt;&lt;br /&gt;四番目。英語は絶対に意地でも覚えろ。これは英語が好きとか嫌いとか関係なく必須です。覚えてください。なぜかというとあなたの目の前にあるコンピューター自体が基本的には英語のような言語しか理解出来ないから（日本語もついでに表示できるよっていう程度に思っておけばよいかと）と、そのコンピューターの中身を作っている連中のほとんどが英語でしゃべっているからです。当然文章も全部英語です。今後もこの状態が変わることはまずないでしょう。なので意地でも覚えてください。どうしても嫌ならば、最後の手段。海外のゲームを買ってきて辞書片手に英語字幕のままプレイしてください。私はこれで覚えました。&lt;br /&gt;&lt;br /&gt;最後、入門書を読みましょう。ぶっちゃけ私なんぞに聞くよりそのほうが何倍もいいです（これが言いたかった！）。でもどれを買えばいいかって？これが難しい。でも基本的にはGoogle先生に聞くか、エライ人に聞くかですよね？ここではひとつだけ私が最も好きな本を紹介しておきます。&lt;br /&gt;&lt;br /&gt;&lt;table  border="0" cellpadding="5"&gt;&lt;tr&gt;&lt;td valign="top"&gt;&lt;a href="http://www.amazon.co.jp/%E3%82%B2%E3%83%BC%E3%83%A0%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9E%E3%81%AB%E3%81%AA%E3%82%8B%E5%89%8D%E3%81%AB%E8%A6%9A%E3%81%88%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84%E6%8A%80%E8%A1%93-%E5%B9%B3%E5%B1%B1-%E5%B0%9A-%E6%A0%AA%E5%BC%8F%E4%BC%9A%E7%A4%BE%E3%82%BB%E3%82%AC/dp/4798021180%3FSubscriptionId%3D15SMZCTB9V8NGR2TW082%26tag%3Dakisutesama-22%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D4798021180" target="_blank"&gt;&lt;img src="http://ecx.images-amazon.com/images/I/51auHbvDazL._SL160_.jpg" border="0" alt="4798021180" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;font size="-1"&gt;&lt;a href="http://www.amazon.co.jp/%E3%82%B2%E3%83%BC%E3%83%A0%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9E%E3%81%AB%E3%81%AA%E3%82%8B%E5%89%8D%E3%81%AB%E8%A6%9A%E3%81%88%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84%E6%8A%80%E8%A1%93-%E5%B9%B3%E5%B1%B1-%E5%B0%9A-%E6%A0%AA%E5%BC%8F%E4%BC%9A%E7%A4%BE%E3%82%BB%E3%82%AC/dp/4798021180%3FSubscriptionId%3D15SMZCTB9V8NGR2TW082%26tag%3Dakisutesama-22%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D4798021180" target="_blank"&gt;ゲームプログラマになる前に覚えておきたい技術&lt;/a&gt;&lt;img src="http://www.assoc-amazon.jp/e/ir?t=akisutesama-22&amp;l=ur2&amp;o=9" width="1" height="1" style="border: none;" alt="" /&gt;&lt;br /&gt;平山 尚(株式会社セガ) &lt;br /&gt;秀和システム  2008-11-15&lt;br /&gt;&lt;br /&gt;&lt;/font&gt;&lt;font size="-2"&gt;by &lt;a href="http://www.goodpic.com/mt/aws/index.html" &gt;G-Tools&lt;/a&gt;&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;セガの中の人が書いている本なので大変スパルタですが、非常にためになります。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■ゲームプログラマーに必要なスキル？&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;いままではとっかかりのところを説明しましたが、うってかわって仕事でゲームを作るにはこれぐらいのスキルが必要だろうというところです。私は本業がゲームプログラマーではないのでなんともですが、これぐらいは知っておかないとなーと思ってます。なので以下の項目は &lt;span style="font-weight:bold;"&gt;好き嫌いかかわらず覚えなくてはなりません。&lt;/span&gt;&lt;ul&gt;&lt;li&gt;プログラム言語系&lt;ul&gt;&lt;li&gt;C&lt;/li&gt;&lt;li&gt;C++&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;学問系&lt;ul&gt;&lt;li&gt;数学, 特に幾何学, 平面幾何は最低限必要, 3次元以上のものが分かれば嬉しい&lt;ul&gt;&lt;li&gt;ベクトル&lt;/li&gt;&lt;li&gt;行列&lt;/li&gt;&lt;li&gt;三角関数&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;物理, 特に運動物理&lt;/li&gt;&lt;li&gt;英語&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;C, C++はおそらく当分の間はゲームプログラミングの主流言語であり続けるので、覚えておいて全く損なしです。というか、メモリ管理を自分でできない言語でゲームのコアエンジンをかくのは絶対不可能なはずなので、将来的にもC, C++でなくてもそれと同等程度の言語が使われるはずです。&lt;br /&gt;&lt;br /&gt;OpenGLとかDirectXを含めていないのは、そんな低レベルなところを直接自分で触ることはまずないと踏んでいるからです。行列の概念さえ理解できていればゲームエンジンにお任せできます。&lt;br /&gt;&lt;br /&gt;あと数学の授業は真面目に受けておいたほうがいいです。どこの学校の、文系でも理系でも何でもいいので、嘘でもいいのでうけておきましょう。どうせ細かいことまで覚えて居られませんが、キーワードだけ覚えておけば後からGoogle先生に聞くことが出来ます。私は数学をサボっていたせいで、この年にして勉強し直しです＞＜&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■まとめ&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;こんだけ書いておいて何なんですが、私ゲームプログラマじゃないんです！（キリッ&lt;br /&gt;&lt;br /&gt;いや、 &lt;a href="http://xacariva.jp"&gt;ゲームっぽいもの&lt;/a&gt; なら作ったことあるんですよ一応＞＜&lt;br /&gt;&lt;br /&gt;あ、そうだ、もし世の中のゲームプログラマになりたい中学三年生ぐらいのお子さんをお持ちのお母さん方が万が一 &lt;del&gt;何かの間違いで&lt;/del&gt; このページをご覧になってらっしゃいましたら、一言だけお願い申し上げます。どうかあたたかい目で見守ってあげてください。やりたいとお子さんがおっしゃられたことをやらせてあげてください。私は中学生高校生の身にもかかわらず家に行きこもってネトゲばっかりしてたり、山口から一人で新幹線に乗って大阪東京までネット友達の元まで遊びに行ってましたが、それでも両親は反対しませんでした。おかげさまでネトゲから英語を無駄に身につけたり東京に交友関係ができて東京で就職する際に助かったりいろいろいいことがありました。 &lt;del&gt;そのかわり彼女がいないんですが&lt;/del&gt; 今ではものすごく感謝しておりますので、どうかよろしくお願いします。&lt;br /&gt;&lt;br /&gt;おしまい。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-2890904573018930704?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/2890904573018930704/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=2890904573018930704' title='3 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/2890904573018930704'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/2890904573018930704'/><link rel='alternate' type='text/html' href='http://akisute.com/2010/10/blog-post.html' title='ゲームプログラマになりたい中学三年生のためにアドバイスを考えてみた'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-5395061704551344630</id><published>2010-10-10T20:00:00.010+09:00</published><updated>2011-05-29T20:07:06.276+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='レビュー'/><category scheme='http://www.blogger.com/atom/ns#' term='iPad'/><category scheme='http://www.blogger.com/atom/ns#' term='スタイラス'/><title type='text'>iPad 用スタイラス oStylus を試してみた</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_9HdIXu4872o/TLGmgv2aZdI/AAAAAAAACiM/Sa-yEBfGgOA/s1600/Photo+10%E6%9C%88+10,+7+46+21+%E5%8D%88%E5%BE%8C.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 299px;" src="http://4.bp.blogspot.com/_9HdIXu4872o/TLGmgv2aZdI/AAAAAAAACiM/Sa-yEBfGgOA/s400/Photo+10%E6%9C%88+10,+7+46+21+%E5%8D%88%E5%BE%8C.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5526381299291022802" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;つい最近販売開始した oStylus という全く新しいタイプのスタイラスを購入して二週間ほど使ってみましたので、レビューを書いてみます。&lt;br /&gt;&lt;br /&gt;2011/02/01追記 - 新価格など記載&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■そもそも oStylus って何？&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://ostylus.com/"&gt;http://ostylus.com/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://japanese.engadget.com/2010/07/14/ostylus/"&gt;http://japanese.engadget.com/2010/07/14/ostylus/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;とあるカナダの会社が作った、全金属製の静電誘導式タッチパネル用（早い話が iPad 用）スタイラスです。最大の特徴はこれまでにない全金属製であるということ（なんと先端まで金属です）と、なにより先端のタッチ部分が &lt;span style="font-weight:bold; color:#cc0000;"&gt;Oの字&lt;/span&gt; になっていてタッチ面を見ながら描画ができるという点です。2010/10/10現在はまだ早期生産フェーズということで、限定250本のみ販売。1本75ドルでした。限定モデルにはすべて刻印が彫られており、私のスタイラスは058番です。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■最初に結論&lt;/span&gt;&lt;br /&gt;&lt;br /&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;ul&gt;&lt;li&gt;価格が非常に高い（75ドル）&lt;/li&gt;&lt;li&gt;2010/10/10現在まだ量産されていないため簡単には手に入らない&lt;/li&gt;&lt;li&gt;長くて重い、持ち運びには全く向かない&lt;/li&gt;&lt;li&gt;ペン先の自由度が1軸しかないため慣れるまで書きづらい、慣れてもちょっとツラい&lt;/li&gt;&lt;li&gt;余りにも滑りが良く、ペンと紙とは違った感覚のため、字が書きづらい&lt;/li&gt;&lt;li&gt;保護用のビニールが貼ってあるが、それでもiPadの表面にダメージが入る可能性がある&lt;/li&gt;&lt;/ul&gt;それでは個別に見ていきます。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■外見&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;全金属製で重さは100gちょっとぐらい、太さは一般的な鉛筆と同じぐらい、長さは日本で一般的に出回っているボールペンなどよりちょっと長い感じです。慣れるまで重くて長く感じます。慣れても大きめのため持ち運びには大変不便です。簡単に携帯できる Pogo Sketch と異なり、 iPad と一緒に持って歩くには何らかの工夫が必要になると思います。&lt;br /&gt;&lt;br /&gt;先端の針金みたいなところは一件弱そうに見えますが、頑丈に作られている上に素材も丈夫で、そうそう簡単には破損しません。また金属であるためスポンジタイプのスタイラスと違い摩耗がほとんど発生しません。長持ちします。&lt;br /&gt;&lt;br /&gt;Oの字部分の裏にはビニールが貼られており、そのおかげで iPad の表面に傷を付けないですみます。また滑りも良いです。野外広告用のビニールだそうで、耐久性も抜群だとか。このビニールは本体とは別に2つ添付されているので、万が一はげてしまっても安心です。&lt;br /&gt;&lt;br /&gt;実際に二週間ほど書いてみたところ、目立つようなキズは確かに発生しませんでしたが、表面に貼ってある保護シート（エレコム製）にほんのわずかながら擦り傷のような後が残りました。&lt;a href="http://www.micro-solution.com/pd/ipad/pgaf-ipad.html"&gt;保護シートをに貼り替えてみたところ&lt;/a&gt;いまのところそのようなキズは発生しておりません。保護シートの質によってダメージが発生するのかもしれません。保護シート無しで直接本体に触れさせたときのダメージは今のところ不明です。言われなければ気づかないようなレベルですが、それでも気になる方は oStylus の使用を避けた方が無難です。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■動作&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;動作についてはこちらの公式ビデオを見るのが一番です。&lt;br /&gt;&lt;object width="640" height="390"&gt;&lt;param name="movie" value="http://www.youtube.com/v/YwYSDmsmvbI&amp;hl=en_US&amp;feature=player_embedded&amp;version=3"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowScriptAccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/YwYSDmsmvbI&amp;hl=en_US&amp;feature=player_embedded&amp;version=3" type="application/x-shockwave-flash" allowfullscreen="true" allowScriptAccess="always" width="640" height="390"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;簡単に補足しますと、まず形状が独特であるため、使い慣れるまで非常に苦労します。長くて重いですし、先端は自由度が1軸しかないため Pogo Sketch のペン先に比べてペンと同じように書きづらいです。しかしながらひとたび慣れてしまうと、このスタイラスのメリットがどんどん生きてきます。金属製だけあってタッチ感度は群を抜いてダントツですし、ペン先のすべりも表面のビニールのおかげか非常に良く、まるで抵抗を感じません。スルスル書けます。ペン先が見えるためズームしなくても細かい入り組んだ線が簡単に書けます。デザイナーさんが絵を描くときに使えそうです。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■まとめ&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;これまで様々な種類のスタイラスを試しましたが、全く新しく他に例がない独特なスタイラスだと思います。書き味も独特です。個人的には手書きで文字を書いたりするときには Pogo Sketch のほうが実際のペンに近い感覚なので好きなのですが、細かい線を引いたりデザインをしたりする人にはこちらの方が大きくて安定し接地面を見ながら描くことができるのでお勧めです。&lt;br /&gt;&lt;br /&gt;2010/10/10現在はまだ価格も高く簡単には手に入らないのですが、今後量産が進むかどうか楽しみなアイテムです。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■2010/10/30追記&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;作者のAndrewさんから次の量産型モデルについてお知らせをいただきました！それによると、次のモデルはなんと半額の$37.50、今の円高を利用すれば3000円とちょっとで買えるようになるそうです！送料は以前かかりますがかなりの進歩だと思います。&lt;br /&gt;&lt;br /&gt;また、以前使っていたときに表面にうっすら傷が入ったと書きましたが、新しくシートを貼り替えて一ヶ月ほど使っていますが全く傷が入っていません。使い方の問題か、もしくはシートの品質の問題だったようです。また、次バージョンではさらに傷がつきにくくなるよう先端の加工が見直されるとのことなので、ますます楽しみです。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■2011/02/01追記&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://ostylus.com/order.html"&gt;http://ostylus.com/order.html&lt;/a&gt; から$37.50と送料で購入できるようになっています！私が持っている早期生産モデルから改良も施されているようです。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-5395061704551344630?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/5395061704551344630/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=5395061704551344630' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/5395061704551344630'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/5395061704551344630'/><link rel='alternate' type='text/html' href='http://akisute.com/2010/10/ipad-ostylus.html' title='iPad 用スタイラス oStylus を試してみた'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_9HdIXu4872o/TLGmgv2aZdI/AAAAAAAACiM/Sa-yEBfGgOA/s72-c/Photo+10%E6%9C%88+10,+7+46+21+%E5%8D%88%E5%BE%8C.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-7202556818079825449</id><published>2010-10-05T13:28:00.003+09:00</published><updated>2010-10-05T13:34:33.970+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Android SDK 2.2'/><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><category scheme='http://www.blogger.com/atom/ns#' term='開発'/><title type='text'>Android のメモリ管理は大変です</title><content type='html'>&lt;span style="font-weight:bold; font-size:110%;"&gt;■理想&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;AndroidってJavaだからメモリ管理なんてしなくてもいいよね！！&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;なんて思っていた時代が私にもありました・・・&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■現実&lt;/span&gt;&lt;pre&gt;    @Override&lt;br /&gt;    protected void onDestroy() {&lt;br /&gt;        super.onDestroy();&lt;br /&gt;        // 画面が回転した時など、Activityが破棄されるときに呼び出されます&lt;br /&gt;        // すべてのメモリはここで開放します&lt;br /&gt;        // - 特に危険なのが内部クラス（MyWebChromeClientなど）、正しく開放しないとActivityが開放されません&lt;br /&gt;        // - セットしたbackgroundのcallbackもnullにしないと開放が行われません&lt;br /&gt;        // - webViewのdestroy()を忘れると後からGCが走ったときにVMがクラッシュします&lt;br /&gt;        this.webView.stopLoading();&lt;br /&gt;        this.webView.setWebChromeClient(null);&lt;br /&gt;        this.webView.setWebViewClient(null);&lt;br /&gt;        this.unregisterForContextMenu(this.webView);&lt;br /&gt;        this.webView.destroy();&lt;br /&gt;        this.webView = null;&lt;br /&gt;&lt;br /&gt;        Drawable backgroundDrawable = this.backgroundViewGroup.getBackground();&lt;br /&gt;        backgroundDrawable.setCallback(null);&lt;br /&gt;        this.backgroundViewGroup.setBackgroundDrawable(null);&lt;br /&gt;        this.backgroundViewGroup = null;&lt;br /&gt;        this.mainViewGroup = null;&lt;br /&gt;        this.anotherViewGroup = null;&lt;br /&gt;    }&lt;/pre&gt;これだけやらないと平気でクラッシュします。マジです。しかもGCが走るまでクラッシュしないとかそういう厄介すぎる現象に２回ほど遭遇しました。&lt;br /&gt;&lt;br /&gt;WeakReferenceとか使えばいいんでしょうけど面倒なんですよねぇ。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■Google曰く&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://d.hatena.ne.jp/nakamura001/20101002/1286015483"&gt;http://d.hatena.ne.jp/nakamura001/20101002/1286015483&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;iPhoneより普通に厳しい気がするのは気のせいでしょうか&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■結論&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;AndroidはJavaではないのできちんとメモリ管理をしましょう！&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-7202556818079825449?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/7202556818079825449/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=7202556818079825449' title='4 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/7202556818079825449'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/7202556818079825449'/><link rel='alternate' type='text/html' href='http://akisute.com/2010/10/android.html' title='Android のメモリ管理は大変です'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-7880775324058508853</id><published>2010-09-12T12:27:00.004+09:00</published><updated>2010-09-12T12:33:44.805+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iOS 4.1'/><category scheme='http://www.blogger.com/atom/ns#' term='iPhone'/><category scheme='http://www.blogger.com/atom/ns#' term='iPad'/><category scheme='http://www.blogger.com/atom/ns#' term='開発'/><title type='text'>iPhone 開発規約まとめ</title><content type='html'>あんまり iOS 上での開発規約とか見かけないので、試しに私が今個人/会社で使っている開発規約を公開してみることにしました。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■設計&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;設計は所謂 MVC と呼ばれる設計モデルを採用します。ただし、厳密な MVC というわけではなく、以下のような区分になっています。&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Model&lt;/span&gt;&lt;br /&gt;Core Data を使用します。通常 MVC での Model というと業務ロジック等を含めた業務モデル一般すべてを含むのですが、私の場合は特に Core Data の NSManagedObject を Model として扱い、 Model 単体のみで完結するロジックのみを Model に記述します。たとえば、&lt;ul&gt;&lt;li&gt;Core Data から対象の Model とその関連 Model 取得&lt;/li&gt;&lt;li&gt;Model の新規作成&lt;/li&gt;&lt;li&gt;新規作成時、更新時に自動的に Model のプロパティを更新する&lt;/li&gt;&lt;li&gt;Model のプロパティの値を元に幾何学計算をしたり、一時的に使うキャッシュを用意したりする&lt;/li&gt;&lt;/ul&gt;などです。実際のコードのサンプル (ニュースサイトのニュースを表す News モデルの実装) はこんな感じになります:&lt;pre&gt;#import "News.h"&lt;br /&gt;&lt;br /&gt;@implementation News&lt;br /&gt;&lt;br /&gt;@dynamic body;&lt;br /&gt;@dynamic title;&lt;br /&gt;@dynamic imageURL;&lt;br /&gt;@dynamic objectId;&lt;br /&gt;@dynamic dateCreated;&lt;br /&gt;@dynamic dateUpdated;&lt;br /&gt;@dynamic sortOrder;&lt;br /&gt;&lt;br /&gt;@end&lt;br /&gt;&lt;br /&gt;//----------------------------------------------------------------------------------------&lt;br /&gt;// ここから上は .xcdatamodel ファイルから自動生成されたコードなので触れないようにします。&lt;br /&gt;//----------------------------------------------------------------------------------------&lt;br /&gt;&lt;br /&gt;#import "AppDelegate.h"&lt;br /&gt;&lt;br /&gt;@implementation News (NSManagedObject)&lt;br /&gt;- (void)awakeFromInsert {&lt;br /&gt;    [super awakeFromInsert];&lt;br /&gt;    // Insert&lt;br /&gt;    self.dateCreated = [NSDate date];&lt;br /&gt;}&lt;br /&gt;- (void)willSave {&lt;br /&gt;    [super willSave];&lt;br /&gt;    // Update&lt;br /&gt;    // DO NOT DO THIS in here because updating self.dateUpdated will call -willSave method recursively until this application crashes!&lt;br /&gt;    // Use NSManagedObjectContextWillSaveNotification / NSManagedObjectContextObjectsDidChangeNotification and watch the time delta of previous change&lt;br /&gt;    // If the time delta is small enough to ignore, do not update dateUpdated property to avoid infinite loop&lt;br /&gt;    //self.dateUpdated = [NSDate date];&lt;br /&gt;}&lt;br /&gt;- (void)awakeFromFetch {&lt;br /&gt;    [super awakeFromFetch];&lt;br /&gt;    // Select&lt;br /&gt;}&lt;br /&gt;@end&lt;br /&gt;&lt;br /&gt;@implementation News (DBAccessors)&lt;br /&gt;+ (NSArray *)all {&lt;br /&gt;    AppDelegate *appDelegate = [AppDelegate appDelegate];&lt;br /&gt;    NSFetchRequest *request = [appDelegate.managedObjectModel fetchRequestTemplateForName:@"allNews"];&lt;br /&gt;&lt;br /&gt;    // Sort by sortOrder, ASC&lt;br /&gt;    NSArray *sortDescriptors = [NSArray arrayWithObjects:&lt;br /&gt;                                [[[NSSortDescriptor alloc] initWithKey:@"sortOrder" ascending:YES] autorelease],&lt;br /&gt;                                nil];&lt;br /&gt;    [request setSortDescriptors:sortDescriptors];&lt;br /&gt;&lt;br /&gt;    NSError *error = nil;&lt;br /&gt;    NSArray *resultArray = nil;&lt;br /&gt;    if (!(resultArray = [appDelegate.managedObjectContext executeFetchRequest:request error:&amp;error])) {&lt;br /&gt;        // handle the error;&lt;br /&gt;        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);&lt;br /&gt;        return nil;&lt;br /&gt;    }&lt;br /&gt;    return resultArray;&lt;br /&gt;}&lt;br /&gt;+ (id)get:(NSString *)targetId {&lt;br /&gt;    AppDelegate *appDelegate = [AppDelegate appDelegate];&lt;br /&gt;    NSDictionary *substitutionVariables = [NSDictionary dictionaryWithObject:targetId&lt;br /&gt;                                                                      forKey:@"objectId"];&lt;br /&gt;    NSFetchRequest *request = [appDelegate.managedObjectModel fetchRequestFromTemplateWithName:@"getNews"&lt;br /&gt;                                                                         substitutionVariables:substitutionVariables];&lt;br /&gt;&lt;br /&gt;    NSError *error = nil;&lt;br /&gt;    NSArray *resultArray = nil;&lt;br /&gt;    if (!(resultArray = [appDelegate.managedObjectContext executeFetchRequest:request error:&amp;error])) {&lt;br /&gt;        // handle the error;&lt;br /&gt;        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);&lt;br /&gt;        return nil;&lt;br /&gt;    }&lt;br /&gt;    return [resultArray lastObject];&lt;br /&gt;}&lt;br /&gt;+ (void)deleteAll {&lt;br /&gt;    AppDelegate *appDelegate = [AppDelegate appDelegate];&lt;br /&gt;    NSFetchRequest *request = [appDelegate.managedObjectModel fetchRequestTemplateForName:@"allNews"];&lt;br /&gt;&lt;br /&gt;    NSError *error = nil;&lt;br /&gt;    NSArray *resultArray = nil;&lt;br /&gt;    if (!(resultArray = [appDelegate.managedObjectContext executeFetchRequest:request error:&amp;error])) {&lt;br /&gt;        // handle the error;&lt;br /&gt;        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);&lt;br /&gt;        return;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // Delete all objects fetched&lt;br /&gt;    for (NSManagedObject *obj in resultArray) {&lt;br /&gt;        [appDelegate.managedObjectContext deleteObject:obj];&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;@end&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Operation&lt;/span&gt;&lt;br /&gt;本来の MVC モデルには存在しませんが、私は特別に Operation という区分をもうけています。定義は以下の通り。&lt;ul&gt;&lt;li&gt;一つの業務モデル、業務ロジックを完結させるひとまとまりのロジックであること。要するに本来の MVC モデルの業務ロジック的要素であること。 もっと言うなら Operation だけを切り出して単体テストできること。&lt;/li&gt;&lt;li&gt;それなりに重要でかつ量があり、 Controller や Model から共有的に呼びだされること。&lt;/li&gt;&lt;li&gt;非同期で処理ができること。&lt;/li&gt;&lt;li&gt;NSOperation クラスのサブクラスにすること。&lt;/li&gt;&lt;/ul&gt;たとえばインターネット経由で API を実行して結果を Model に突っ込む処理などは Operation として実装しています。 NSOperation として実装することで、非同期処理が簡単にできるようになるだけではなく、 タスクの依存関係を決めて先に親タスクが実行されるのを待つようにしたり、現在の状態を厳密に判定したり、タスクをキャンセルしたりするのが容易になります。また、将来的に iPhone / iPad のCPUがマルチコアになった場合、 NSOperation を継承しておけばほとんど何もしなくてもその恩恵を受けることができるはずです。&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;View&lt;/span&gt;&lt;br /&gt;ビューです。主に UIKit および Three20 を用いて構築し、必要に応じてその他のビューライブラリを組み込みます。個人的には UIView のサブクラス一般をすべて View として扱っています。 View には描画ロジックと幾何学計算などの補助ロジック、およびそれに必要な最小限のデータのみを持たせるようにします。状態を持ってもかまいませんが、状態のコントロールを View 自身が行うのはできる限り避けます。タッチイベントのハンドリングは必要に応じて View で touchesBegin: などを実装して行いますが、基本的には Controller 側で UIGestureRecognizer を用いて行います。&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Controller&lt;/span&gt;&lt;br /&gt;コントローラーです。私の中での定義は UIViewController のサブクラスです。アプリの内容に応じて UIKit と Three20 を使い分けます。 本来 Controller は全体の流れのみを管理し実際の処理を行ってはならないということになっていますが、 UIViewController の性質を鑑みて、私は次のように Controller の役割を定義しています。&lt;ul&gt;&lt;li&gt;View の管理。&lt;/li&gt;&lt;li&gt;画面遷移, 要するに Controller 間の遷移の管理。&lt;/li&gt;&lt;li&gt;タッチイベント、ジェスチャイベント、加速度計などからの入力の受付と処理。&lt;/li&gt;&lt;li&gt;各種 UI コンポーネントの Delegate 処理。 UITextView, UIPopoverController, UIActionSheet, などなどなど多岐にわたります。&lt;/li&gt;&lt;li&gt;Operation 完了時の処理など、各種 Notification を受け付けて処理。&lt;/li&gt;&lt;li&gt;上記に必要になるデータ/メソッドの定義。 View に持たせるぐらいならこちらに持たせる。他に持たせるところがないなら Controller にすべて持たせる。&lt;/li&gt;&lt;/ul&gt;ということで、 Controller を名乗っていますが実際にはかなり自分で処理をします。こんなのいちいち分けていたら大変ですし・・・といういいわけです。実際のコードサンプルはお見せできないのですが、実装の概要はこんな感じです&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_9HdIXu4872o/TIxIzOnmCVI/AAAAAAAACh8/TYjUI0bdlwc/s1600/sample+view+controller+implementation+overview.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 337px; height: 400px;" src="http://1.bp.blogspot.com/_9HdIXu4872o/TIxIzOnmCVI/AAAAAAAACh8/TYjUI0bdlwc/s400/sample+view+controller+implementation+overview.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5515863688556710226" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Application Delegate&lt;/span&gt;&lt;br /&gt;これも本来の MVC モデルには存在せず、本来は Controller として扱うべき物だと思いますが、私は特別に分けています。 Application Delegate は所謂アプリケーショングローバルなデータや設定、オブジェクト、ユーティリティメソッドを管理するものとして扱います。たとえば、&lt;ul&gt;&lt;li&gt;Operation 駆動用の NSOperationQueue&lt;/li&gt;&lt;li&gt;Model のための NSManagedObjectContext / NSManagedObjectModel / NSPersistentCoordinator&lt;/li&gt;&lt;li&gt;現在通信可能か否かを判定するためのユーティリティメソッド&lt;/li&gt;&lt;li&gt;アプリケーショングローバルな Notification を受け取って Application Delegate のプロパティとしてセットする&lt;/li&gt;&lt;/ul&gt;などです。これらはほぼすべてのアプリで絶対に必要になるのでテンプレ化しています。&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■Xcodeプロジェクト&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;プロジェクトのグループはこんな感じで分けます。&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_9HdIXu4872o/TIxIzvsPhVI/AAAAAAAACiE/PBCxp8VnQ7s/s1600/xcode+project+sample.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 389px;" src="http://4.bp.blogspot.com/_9HdIXu4872o/TIxIzvsPhVI/AAAAAAAACiE/PBCxp8VnQ7s/s400/xcode+project+sample.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5515863697434576210" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;ビルド設定については、プロジェクト全体のビルド設定は可能な限り使わないようにして、ターゲットごとのビルド設定 ( &lt;code&gt;Cmd+Option+E&lt;/code&gt; ) を主に使います。ターゲットが例え複数に分かれても常に同じ物を使うところはプロジェクト全体の設定を変更します。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■命名規則&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;大体以下のような方針でやっています。&lt;ul&gt;&lt;li&gt;Foundation や UIKit など Apple の使っている命名規則に似せること。似てないシグネチャは即リファクタリング対象。&lt;/li&gt;&lt;li&gt;ミススペル、Typo、意味のわからない英単語 ( &lt;span style="font-weight:bold;"&gt;registとか&lt;/span&gt; ) は一文字一単語であろうとも発見した瞬間即リファクタリング対象。英語辞書のソースは &lt;a href="http://www.alc.co.jp/"&gt;http://www.alc.co.jp/&lt;/a&gt; とする。&lt;/li&gt;&lt;li&gt;名前はどれだけ長くなろうとも絶対に省略しないこと。 &lt;code&gt;updUniqUsr&lt;/code&gt; とか発見したら即リファクタリング対象。逆に &lt;code&gt;BPSuperDuperViewControllerDidFinishedUberTaskNotification&lt;/code&gt; とかは表彰モノ。&lt;ul&gt;&lt;li&gt;これを &lt;code&gt;BPSDVCDFUTN&lt;/code&gt; とか略した奴が現れたら即 &lt;span style="font-weight:bold; color:#cc0000;"&gt;SATSUGAI&lt;/span&gt; モノです&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■まとめ&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;ここまで書いておいて何ですが、要するに &lt;span style="font-weight:bold; color:#cc0000;"&gt;一貫した基準があるなら&lt;/span&gt; &lt;span style="font-weight:bold;"&gt;自分らの好きなようにするのが一番いい&lt;/span&gt; のかなと思います。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-7880775324058508853?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/7880775324058508853/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=7880775324058508853' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/7880775324058508853'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/7880775324058508853'/><link rel='alternate' type='text/html' href='http://akisute.com/2010/09/iphone.html' title='iPhone 開発規約まとめ'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_9HdIXu4872o/TIxIzOnmCVI/AAAAAAAACh8/TYjUI0bdlwc/s72-c/sample+view+controller+implementation+overview.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-4778241136082140621</id><published>2010-09-12T10:09:00.004+09:00</published><updated>2010-09-12T10:27:27.592+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='お知らせ'/><category scheme='http://www.blogger.com/atom/ns#' term='iPad'/><category scheme='http://www.blogger.com/atom/ns#' term='App Store'/><title type='text'>idea mapper for iPad が有料ランキング一位になりました</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_9HdIXu4872o/TIwotnKZZHI/AAAAAAAACh0/7QnTEcOR0nM/s1600/idea+mapper+got+the+top.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 324px;" src="http://2.bp.blogspot.com/_9HdIXu4872o/TIwotnKZZHI/AAAAAAAACh0/7QnTEcOR0nM/s400/idea+mapper+got+the+top.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5515828407693829234" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;弊社ビープラウドが開発を担当しました idea mapper for iPad がなんと日本の App Store で有料ランキング一位を取ってしまいましたので、記念POST。 Good Reader や i文庫HD より上ってマジですか・・・＞＜　ほんと企画とデザインをされた&lt;a href="http://www.cytech.co.jp/"&gt;サイテックさん&lt;/a&gt;のおかげだと思います。ありがとうございます。&lt;br /&gt;&lt;br /&gt;ところで気になったのがランキングの推移の仕方。このアプリ、実は日本の有名どころのレビューサイトに全然レビューして貰ってないんです。少なくとも私が自分で観測した範囲では、2010/09/12現在 &lt;a href="http://www.appbank.net/"&gt;AppBankさん&lt;/a&gt;にも&lt;a href="http://www.apptoiphone.com/"&gt;apptoiさん&lt;/a&gt;にも&lt;a href="http://ipodtouchlab.com/"&gt;ラボさん&lt;/a&gt;にも&lt;a href="http://www.macotakara.jp/blog/"&gt;お宝鑑定団さん&lt;/a&gt;にも掲載されていなくて。実際初日は仕事効率化カテゴリ30位ぐらいだったのに、一週間ぐらいかけてじわじわ伸ばしてきて今の順位に。&lt;br /&gt;&lt;br /&gt;これは個人的にはかなり衝撃でした。というのもことあるごとに聞いていたiPhoneアプリのセールス/マーケティングの基礎が、「大手のレビューサイトにレビューを載せて貰う」ことだったからです。ではどこからこれだけ人が流入したのか？と考えてみたところ、&lt;a href="https://twitter.com/yatabe"&gt;サイテックの社長さん&lt;/a&gt;が凄く積極的にTwitterで宣伝してくださって、口コミでどんどん広がっていき、ランキングに載ってそのまま加速度的にダウンロードが増えたのではないかなと思ってます。Twitterの力は偉大と考えるべきなのか、日本の App Store の規模が小さいおかげで助かったと考えるべきなのか、どっちなのかは分かりませんが・・・何かの参考になれば幸いです。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-4778241136082140621?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/4778241136082140621/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=4778241136082140621' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/4778241136082140621'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/4778241136082140621'/><link rel='alternate' type='text/html' href='http://akisute.com/2010/09/idea-mapper-for-ipad.html' title='idea mapper for iPad が有料ランキング一位になりました'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_9HdIXu4872o/TIwotnKZZHI/AAAAAAAACh0/7QnTEcOR0nM/s72-c/idea+mapper+got+the+top.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-6188468949225174951</id><published>2010-09-05T19:09:00.003+09:00</published><updated>2010-09-05T19:13:50.601+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iPhone OS 4.0.2'/><category scheme='http://www.blogger.com/atom/ns#' term='iPhone'/><category scheme='http://www.blogger.com/atom/ns#' term='iPad'/><category scheme='http://www.blogger.com/atom/ns#' term='Three20'/><title type='text'>Three20 の TTURLRequest は POST メソッドのリクエストもキャッシュしてしまう</title><content type='html'>Three20 には TTURLRequest という Three20 フレームワークの通信関連を一手に引き受けている通信用クラスがあります。基本的には　NSURLConnection クラスとほぼ同等なのですが、リクエストを作ったりレスポンスを delegate でハンドルするのがより簡単になるように作られていたり、独自のキャッシュを使用してより効率的なキャッシュをするようになっていたり、様々な点で NSURLConnection より優れていて便利に使えます。&lt;br /&gt;&lt;br /&gt;ですがいくつかハマリどころもありまして、今回はそれを紹介します。ちなみに今回使用した Three20 のバージョンは http://github.com/facebook/three20 の default ブランチの 2010/09/05 付での最新コミットです。今後修正される可能性があります。&lt;br /&gt;&lt;br /&gt;実は TTURLRequest は、デフォルトでは HTTP メソッドの種類に関係なく、一律すべてのURLをキャッシュするようになってしまっています。そのため、キャッシュ設定をせずに POST メソッドを使って Web API を実行したり、 RESTful な Webアプリ に PUT や DELETE を送ってしまうと、二回目以降のリクエストがキャッシュされてしまいサーバーにリクエストが飛ばなくなってしまいます。回避方法は以下のどちらかを使うと良いです。&lt;ol&gt;&lt;li&gt;手動でリクエストを作成する際にキャッシュ設定を明示的に指定する&lt;/li&gt;&lt;li&gt;フレームワーク側を書き換えてしまい、　POST, PUT, DELETE 実行時にはキャッシュを無視するようにする&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■手動でリクエストを作成する際にキャッシュ設定を明示的に指定する&lt;/span&gt;&lt;br /&gt;一番簡単です。以下のようにして明示的にキャッシュを使わないように指定します。&lt;pre&gt;TTURLRequest *request = [TTURLRequest requestWithURL:@"http://mypage.example.com/api/something/post" delegate:self];&lt;br /&gt;request.httpMethod = @"POST";&lt;br /&gt;request.cachePolicy = TTURLRequestCachePolicyNone;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■フレームワーク側を書き換える&lt;/span&gt;&lt;br /&gt;でも個人的には GET 以外でリクエスト結果がキャッシュされるのは誰がなんと言おうと不具合だと思っているので、 &lt;code&gt;TTURLRequestQueue.m&lt;/code&gt; の &lt;code&gt;loadRequestFromCache:&lt;/code&gt; メソッドを以下のように書き換えて対応しました。&lt;pre&gt;- (BOOL)loadRequestFromCache:(TTURLRequest*)request {&lt;br /&gt;    if (!request.cacheKey) {&lt;br /&gt;        request.cacheKey = [[TTURLCache sharedCache] keyForURL:request.urlPath];&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if (IS_MASK_SET(request.cachePolicy, TTURLRequestCachePolicyEtag)) {&lt;br /&gt;        // Etags always make the request. The request headers will then include the etag.&lt;br /&gt;        // - If there is new data, server returns 200 with data.&lt;br /&gt;        // - Otherwise, returns a 304, with empty request body.&lt;br /&gt;        return NO;&lt;br /&gt;    //-----------------------------------------------------------------------&lt;br /&gt;    // ここから下が変更点&lt;br /&gt;    //-----------------------------------------------------------------------&lt;br /&gt;    } else if ([request.httpMethod isEqualToString:@"POST"] || [request.httpMethod isEqualToString:@"PUT"] || [request.httpMethod isEqualToString:@"DELETE"]) {&lt;br /&gt;        // HTTP POST/PUT/DELETE should not use cache.&lt;br /&gt;        // Only HTTP GET can use this cache.&lt;br /&gt;        return NO;&lt;br /&gt;    //-----------------------------------------------------------------------&lt;br /&gt;    // ここまでが変更点&lt;br /&gt;    //-----------------------------------------------------------------------&lt;br /&gt;    } else if (request.cachePolicy &amp; (TTURLRequestCachePolicyDisk|TTURLRequestCachePolicyMemory)) {&lt;/pre&gt;これですべてのHTTPリクエストにおいて、 POST, PUT, DELETE 時にキャッシュが使われなくなります。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/42067579805640535-6188468949225174951?l=akisute.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://akisute.com/feeds/6188468949225174951/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=42067579805640535&amp;postID=6188468949225174951' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/6188468949225174951'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/42067579805640535/posts/default/6188468949225174951'/><link rel='alternate' type='text/html' href='http://akisute.com/2010/09/three20-tturlrequest-post.html' title='Three20 の TTURLRequest は POST メソッドのリクエストもキャッシュしてしまう'/><author><name>akisute</name><uri>http://www.blogger.com/profile/14509295337098903238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9HdIXu4872o/SPFJwDG6V_I/AAAAAAAABaY/MwBtaJeUJWo/S220/%E3%83%AB%E3%83%BC%E3%83%9F%E3%82%A201.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-42067579805640535.post-7261261141163376603</id><published>2010-08-29T22:03:00.002+09:00</published><updated>2010-08-29T22:10:55.655+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iPhone'/><category scheme='http://www.blogger.com/atom/ns#' term='iPad'/><category scheme='http://www.blogger.com/atom/ns#' term='開発'/><title type='text'>自分なりの iPhone アプリ開発手法とかこだわりとか書いてみた</title><content type='html'>Twitter で vの人こと &lt;a href="http://twitter.com/voluntas"&gt;@voluntas&lt;/a&gt; さんに &lt;a href="http://twitter.com/voluntas/status/21827489504"&gt;無&lt;/a&gt; &lt;a href="http://twitter.com/voluntas/status/21832088379"&gt;茶&lt;/a&gt; &lt;a href="http://twitter.com/voluntas/status/21833584156"&gt;振&lt;/a&gt; &lt;a href="http://twitter.com/voluntas/status/21833619228"&gt;り&lt;/a&gt; されたので、自分なりのポリシーとかこだわりとか開発手法とかをまとめてみることにしました。今仕事で iPhone アプリの開発を主にやっているので、 iPhone アプリに関する内容が多いですが、それ以外の開発でも使えると思います。&lt;br /&gt;&lt;br /&gt;あまり技術的な内容やツールに関する内容はありません。それらは別エントリーにまとめようと思います。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■大前提: 自分を知る&lt;/span&gt;&lt;br /&gt;まず何はなくともこっからです。なんだか開発とか全然関係ないじゃないか、怪しい自己啓発じゃねえかと思われるかもしれませんが、敵を知り己をを知れば百戦危うからずと昔のエライ人も言ってます。それにそもそも私がどのような人間なのかを理解しないと、せっかくの開発手法もそのまま真似してはうまく合わない・上手く回らない・賛成できないということになりますので、非常に大事だと思います。ということでさっそくまとめてみました。&lt;ul&gt;&lt;li&gt;恐ろしく几帳面である&lt;br /&gt;A型人間です。&lt;br /&gt;Java とか大好きです。逆にカオスなコードが苦手で、 PHP とかは敵です。&lt;br /&gt;掃除してない &lt;a href="http://twitter.com/feiz"&gt;@feiz&lt;/a&gt; や &lt;a href="http://twitter.com/shin_no_suke"&gt;@shin_no_suke&lt;/a&gt; の机とか見てると勝手にゴミを捨てたり掃除したくなります。&lt;br /&gt;Typo とか見つけたら人のコードでも勝手に直します。 Typo するのが嫌なので毎回変数名を決める前に英語辞書を引きます。&lt;/li&gt;&lt;li&gt;ゆとりである&lt;br /&gt;一日の労働時間は八時間までよねー（キリッ&lt;br /&gt;なのでとにかく楽をしたがりです。&lt;br /&gt;そもそも体力が小学生並なので徹夜仕事とかできません。そのような事態に陥らないような仕事の進め方が必要になります。&lt;/li&gt;&lt;li&gt;やたらこだわる&lt;br /&gt;好きなモノは徹底的に好きで嫌いなモノは徹底的に嫌いです。なので評価が極端で言動が偉そうです。すみません＞＜&lt;br /&gt;一歩間違えるとただの頑固者になるので気をつけています。&lt;/li&gt;&lt;li&gt;言動は偉そうだけれども中身は非常に臆病者で弱い&lt;br /&gt;なのでゆとりを失うと一気に迷走します。余裕を常に持てるようにする必要があります。&lt;br /&gt;また周りの皆さんの支援ないと生きていけないと思っていますので、「生意気だけれどもイイ奴」ぐらいのポジションに落ち着きたいと思ってます。&lt;/li&gt;&lt;li&gt;iPhone は俺の嫁、 Cocoa Touch は神環境&lt;br /&gt;もう二度と iPhone の無い世界には戻れません。&lt;br /&gt;10年後ぐらいにはまた別の面白いものがあると思いますが、今のところは iPhone が一番面白いです。&lt;/li&gt;&lt;/ul&gt;似たような方は私と同じやり方を真似してもいいし、真逆な方は私のやり方と真反対をやればうまくいくのではないかと思います。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■三つの大戦略&lt;/span&gt;&lt;br /&gt;私がどういう人間か分かったところで、次は今の仕事のやり方に関して最も根底にある三つの大戦略をまとめてみました。この大戦略にはほとんどツールや言語の話が登場しません。それらは時代が変われば変化してしまうからです。それよりもむしろ、どういう考え方やポリシーで仕事をすれば最も開発生産性が上がるか、というところに着目しています。&lt;ul&gt;&lt;li&gt;徹底的に几帳面にやる&lt;/li&gt;&lt;li&gt;楽をする・楽しむ・楽をさせる・楽しませる&lt;/li&gt;&lt;li&gt;二度とガラケーには戻らないと決心しその通りに行動する&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight:bold;"&gt;徹底的に几帳面にやる&lt;/span&gt;&lt;br /&gt;几帳面なのが武器なので、それを徹底的に生かす方針で開発を進めます。また几帳面さは Objective-C と非常に相性がよいです。たとえばメモリリークが発生してから調査すると非常に大変ですが、発生する前に防ぐことができれば生産性がそれだけ高まるはずです。また KVC/KVO や Core Data など動的言語のような処理を行う箇所では一文字のスペルミスが発見しづらいバグにつながるため、スペルミスチェックを行ったり、命名規則の策定をしたりする必要がありますが、このとき几帳面さが効果的に働きます。&lt;br /&gt;また、余りつまらないところでミスを連発するとテンションも下がるしリズムも崩れ、余裕が無くなってしまい結果として悪いモノができあがってしまうので、それを防ぐためにも几帳面にやるのが効果的だと思ってます。&lt;br /&gt;なにより、これが一番大事だと思うのですが、几帳面にコードを書くのが自分にとって一番楽しく、モチベーションが上がります。つまり逆に言えば、リズミカルにどんどん細かいところを気にしないでガーッとたくさん作るほうが楽しくリズムに乗れてモチベーションも上がる人でしたら、そのようにする方が良いと思います。&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;楽をする・楽しむ・楽をさせる・楽しませる&lt;/span&gt;&lt;br /&gt;四楽運動です（何それ&lt;br /&gt;要するに、&lt;blockquote&gt;自分が楽したい、仕事量は減らして簡単にしたい&lt;br /&gt;仕事は楽しんでやりたい、面白い技術を使ってやりたい&lt;br /&gt;でも自分ばっかり楽したら申し訳ないし楽した分だけしっかりやって楽をさせてあげよう&lt;br /&gt;それにせっかく作るなら楽しいモノを作った方がいいに決まってるからそうしよ&lt;/blockquote&gt;ということです。&lt;br /&gt;この方針に従うと、私の場合、楽ができて楽しいだけではなく、「このようなすばらしい環境で開発させて貰ってありがとう」という感謝の気持ちと「それなりの成果を出さなくてはならない」という責任感が自然と発生するため、非常に開発効率が高まるようです。&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;二度とガラケーには戻らないと決心しその通りに行動する&lt;/span&gt;&lt;br /&gt;うちの会社でもガラケー向けのWebアプリの開発をやっていて、その際の苦労話を聞く機会があります。また、企画やお仕事の提案などでGREEやモバゲーなどのガラケーアプリを見せて貰うことがあります。そのような経験から思うのは、&lt;blockquote&gt;ガラケーはIE6とか比較にならないほど苦労するくせにどうしようもないユーザー体験しか提案できない最悪の開発環境&lt;/blockquote&gt;だということです。たとえばメールの文字コードの扱いとか、特定の機種だけ動かないとかで50台以上の実機でテストしないと駄目とか、Flash lite 1.1はまともに使えないからサーバー側でバイナリ操作してSWFを生成して送り返しているとか、そんなネタを聞くたびにこう、ふつふつとしたものが沸いてきます。&lt;br /&gt;その上お金になるからかバッドノウハウだからか知りませんが、驚くほど情報が出回っていない。調べてもなかなか分からない。とにかく開発者に優しくありません。なによりバッドノウハウを運用しても楽しくない上にイライラして嫌なムードになってしまいます。&lt;br /&gt;確かにガラケーの環境はお客さんからお金を取りやすく儲かりやすいため、会社で取り組むには非常に好都合であるとは思うのですが、やはり私は開発者の身である以上、素直に開発者に優しく、さらには素晴らしいユーザー体験を提供できる環境を選びたいのです。さらに思うだけでは駄目で、実際に iPhone の開発で仕事を取って継続的にお金を稼げるようにしなくてはならないので、そうなれるよう実際に行動する必要があります。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■「徹底的に几帳面にやる」を達成するための戦略&lt;/span&gt;&lt;ul&gt;&lt;li&gt;面倒くさがらずにリファクタリングする&lt;br /&gt;リファクタリングは大事です。納得いくまでリファクタリングします。一文字Typoしたら名前変更、名前が後から気に入らなくなったら変更、クラスの構造を変更、メソッドをパブリックに変更、エトセトラエトセトラ。リファクタリングは他の人がコードを読んだ時の理解を助けてくれるだけではなく、自分自身がリファクタリングのためにコードを理解することになり、今後の設計に役立ちます。自分の考えを整理するという意味でも大事だと思います。&lt;/li&gt;&lt;li&gt;細かくスタートして、ちょっと作って確認し、またちょっと作って確認して繰り返す&lt;br /&gt;特に iPhone での開発は小規模で変更や追加が多く、アップデートも頻繁。必然的にアジャイルな開発が要求されます。そしてなにより、テストケースを書いてテストドリブンで開発するだけの時間的余裕がありません。そんな贅沢なやり方ができるのは長期でずーっとやっていくWebサービスや大規模なシステムだけで、作ってすぐ放棄される事が多い iPhone の開発にはテストドリブンは全く向いていないと思っています。&lt;br /&gt;しかしながら、品質は当然担保しなければなりません。そこで私は小さく作ってすぐに作った箇所を確認し、また少し作って確認・・・という手法をとっています。正しく作る単位をモジュール化することができれば、一端テストしてその部分の品質が保証されればその後の開発ではテスト済みのモジュール内の事は考えなくて済むからです。テスト自体が大変でコストがかかるので、やはりコーディングの段階で几帳面にバグを出さないようにするというのが一番に思えます。&lt;/li&gt;&lt;li&gt;一番面倒で難しそうなところからスタートする&lt;br /&gt;ほとんどの技術者の方はこのような手法を取られていると思うのでわざわざ書くほどのものでもないのですが、それでも一番面倒で難しそうなところからスタートする手法は非常に有効です。上記の手法とも合わせ、一番難しそうなところ一番最初に小さくスタートしてすぐにテストし、品質を保証してしまうのが最も有効です。全体の２割のコードに全体の５割ぐらいの時間をかけて作り、残りの半分はコピペしてプロパティをちょっと書き換えるだけでざざーっと作れるようなところにしてしまう、というのが理想だと思ってます。&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■「楽をする・楽しむ・楽をさせる・楽しませる」を達成するための戦略&lt;/span&gt;&lt;ul&gt;&lt;li&gt;取捨選択をする&lt;br /&gt;ソフトウェア開発で楽をするための一番よい方法は、作らないことです。取捨選択を適切に行ない、不要な枝を切り捨て、必要な枝・競争力のある枝にすべてのエネルギーを集約することで、個性的なアプリを作り出すことが出来ます。個性的でないアプリは供給過多の市場に埋没します。さらに取捨選択は作業をすすめる最中でも大いに役立ちます。たまにお客さんから「あれもなる早、これもなる早、全部最優先で」とかいうお前日本語間違ってるだろといわんばかりの指示が飛んできたりしますが、これは全く話になりません。「最たるもの」とは常にひとつしか存在しないもので、だからこそまずそれから仕事にとりかかることができ、余計な仕事の順序選択思考を避けることができるのです。私自身が優先順位をつけたり指示を出したりする際にも、最優先がひとつ、次に優先がふたつ、それ以下はすべて後回しか切り落としです。そもそも、三つよりたくさんを記憶して同時に処理できる人はまれです。&lt;/li&gt;&lt;li&gt;偉い人の作ったフレームワークとかライブラリをどんどん使わせていただく&lt;br /&gt;ソフトウェア開発で楽をするための二番目に良い方法は、すでに完成しているものを取り込むことです。ということで、フレームワークやライブラリなどは積極的に活用します。ライセンスには気をつけないと大変なことになりますので注意ですが、これらのフレームワークやライブラリは私よりも遥かにすごい人達が時間と手間をかけて作り上げられ、テストもしっかり行った上で公開されているものが多いので、私自身が実装するよりも遥かに信頼できると思っています。もちろん人が作ったものなのでバグや合わない仕様はたくさんありますが、ソースコードを読んで修正すればよいのです。ゼロから自分が作るよりは断然良いです。&lt;/li&gt;&lt;li&gt;とにかく自動化する&lt;br /&gt;とかく人間というのは、単純作業をミスすることにかけては超一流です。頻度の差こそあれ誰しも必ず単純作業をミスします。さらに単純作業は集中力という貴重なリソースを消費します。&lt;br /&gt;二回以上繰り返す単調作業は自動化する。それがたとえ、ソースコードをzipで圧縮してメールでお客さんに送るといった簡単な作業であったとしても、自動化しておくのは非常に役に立ちます。単純作業を避けることで生まれた余剰集中力を、別のところに振り分けることができます。&lt;br /&gt;自動化する手法がわからなかったら調べて勉強します。ここでちょっとわからなくて面倒だからと避けると後から地獄を見ますし、成長できないので、意地でも調べます。&lt;/li&gt;&lt;li&gt;自分に要求されている責任範囲以上の仕事を引き受けて楽をさせてあげる&lt;br /&gt;私は最初の会社の新人教育の際に、「自分が要求されている以上の仕事をしろ」と繰り返し教えられました。実際最初の会社はどちらかというとブラックに属する部類だと思いますし、こういう教えは社畜だの何だのと言われているようですが、私はこの「自分が要求されている以上の仕事をしろ」という考えが好きです。&lt;br /&gt;確かに前の会社で仕事をしている間はこの考えは嫌いでした。なぜなら仕事がつまらない上に余計なことをすると怒られる職場だったからです。バグだらけの共通ライブラリを修正したら余計なことをするなと怒られ、酷い出来栄えのJavaScriptを救済するためにjQueryを突っ込んでみたらこれまた余計なことをするなと言われ。まったくどうしろと・・・。&lt;br /&gt;しかし今は違います。仕事の内容は全部任せていただいていますし、効率化も推奨されています。画像リソースがお客さんからやってこなければ自分で作り、画面の仕様が決まらなければ私が決めて作ってお渡しし、セールスのためにアプリレビューを行ってくれるブログ一覧をまとめてお渡しするなど、とにかく仕事が円滑に進むと思えばなんでもやります。面倒なときもありますが、それより相手の仕事が遅くってイライラして「あいつが悪い、あいつのせいでプロジェクトが失敗した」とか考える方が嫌です。それにちょっと勝手にやりすぎたかと思っても、意外なほど喜んでもらえます。&lt;br /&gt;ただし、何でもかんでもこの方法で一人で引き受けていると私の仕事量が破綻するので、この方法で引き受けるのは一過性の仕事だけにしています。定期的にやらなくてはいけない仕事は自動化するか、やり方を教えてあげてやってもらいます。&lt;/li&gt;&lt;li&gt;細部にこだわれるだけのスケジュール上の余裕を常に持つ&lt;br /&gt;リファクタリングしたり、自分に要求されている範囲以上の仕事をすると、どうしても当初見積りより遥かにたくさんの時間がかかることになります。それにプロジェクトには絶対にトラブルが付きものです。ということで、時間的なゆとりが必要です。私は見積りを提出する際に、自分で余裕を持ってできる見積りに、さらに1.5をかけて提出したりします。提出するときにはこれ時間がかかりすぎじゃないかと言われないかヒヤヒヤしますが、バグを取ったりクオリティを上げたり、突然湧いたトラブルに対処しているうちに、最終的にはそれで大体丁度良くなるので不思議です。お客さんにとっても納期遅延が発生しないため、今のところ大変ご満足頂いております。&lt;br /&gt;特に iPhone アプリはこの余裕を持ってアプリのクオリティを上げる方針が有効に働きやすい気がします。修正が比較的簡単ですぐに行えるWebアプリに比べ、リリースを急いだとしても、ひとたびバグが原因でリジェクトされるとリリースが一週間遅れ、醜いアプリをリリースするとレビューで酷評されと、ろくなことがありません。&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■「二度とガラケーには戻らないと決心しその通りに行動する」を達成するための戦略&lt;/span&gt;&lt;ul&gt;&lt;li&gt;ガラケーの仕事は意地でも断る&lt;br /&gt;「ガラケーは嫌いだけれど、仕事だからしょうがないし・・・」冗談じゃありません。幸いにして iPhone 開発で人材募集をしている会社さんも増えましたし、フリーで出来るお仕事の量も増えています。口だけでなくて行動でやらなければなりませんので、まずガラケーの仕事をお断りです。&lt;/li&gt;&lt;li&gt;せっかく無理言って iPhone のお仕事をやらせてもらっているので、とにかく全力でやる&lt;br /&gt;とまぁこんな具合で無理わがままを通しまして何とか iPhone のお仕事を頂きましたので、その分きっちりお仕事して成果を出して次があるようにしなければなりません。こうして後ろを断つとやっぱりやる気が出ます。また、損益にも気が向くようになります。なにせ赤字垂れ流しではあっという間にガラケーに逆戻りです。利益を出さなくては話になりません。&lt;/li&gt;&lt;li&gt;自分に要求されている責任範囲以上の仕事をやる&lt;br /&gt;一番信用できて一番自分の思い通りに動くのは自分です。まず自分がやることで成功が近づくと考えています。と同時に一番信用できないのも自分なので、人におまかせしたり既存のライブラリなどを活用したりというのも必要になります。なんかすごい矛盾してますが、とにかく自分が一番信用できるけど一番信用できないのです。&lt;/li&gt;&lt;li&gt;次の仕事を持ってきてもらえるように売上とかまで気にする&lt;br /&gt;「開発は物つくるまでが仕事、売るのは営業の仕事・・・」ガラケーでやってください。 iPhone 開発者の人は少人数かフリーの人が多いため、みなさん作ったものを売るところまで考えてらっしゃるようです。ただし、あくまで開発者の立場として売上を気にすることです。本職の営業や企画の方がいらっしゃるときに、私が営業や企画の真似事を始めると破綻します。&lt;/li&gt;&lt;li&gt;以上のようなわがままを聞いてくれる環境に身を置く&lt;br /&gt;「んなもんお前に言われなくてもわかってるわ！そんな理想的な環境あるわけねえ！」すみません、ごもっともです＞＜&lt;br /&gt;結局良い環境で仕事するのが一番で、良い環境は良い人脈と人付き合いがあれば勝手にやってくるみたいなので、まずは勉強会とかに参加しまして良い人付き合いをするのが一番の近道かなぁと思います。&lt;/li&gt;&lt;li&gt;成果はきっちりアピールする&lt;br /&gt;成果はアピールしないと次につながりませんので、きちんとアピールします。幸いにして私は口から先に生まれてきた人間なので、大声で騒ぐのは得意です！しかしアピールというのはやり方を間違えると単なるスパムや嫌がらせに成り下がってしまいます。TPOをわきまえて正しく成果を大声でアピールしましょう。&lt;br /&gt;たとえば &lt;a href="http://twitter.com/iphone_dev_jp"&gt;@iphone_dev_jp&lt;/a&gt; に「新作アプリをリリースしました！」なんて大声で流してもイラッとされるばかりですが、リリースして培った経験や技術情報、お役立ち情報を流せば「あいつはできる」と思ってもらえるわけです。&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight:bold; font-size:110%;"&gt;■チームで作業する際の戦略&lt;/span&gt;&lt;br /&gt;ここまでは主に自分自身に関する内容の戦略でした。が、実際の仕事はもちろん自分ひとりだけではなく複数の関係者やチームのみなさんと進めることになります。ということで最後にチームで作業する際に私の考える戦略をまとめてみました。&lt;ul&gt;&lt;li&gt;大前提: 人数は少なければ少ないほど良い 能力は高ければ高いほど良い 距離は近ければ近いほど良い&lt;br /&gt;これが大前提です。とにかくコストを最小限に保ちつつ、時間あたりの開発能力を最大にする必要があります。大規模開発等では当てはまらないかもしれませんが、仕事の総量が比較的少なめで予算が少なく納期が極めて短い iPhone 開発では、開発・デザイナーあわせて殆どの場合３人以内で足ります。その分各個人の責任範囲が非常に広くなるため、すべてのチームメンバーにそれらの責任を全うできるだけのスキルが必要です。誰しも限界があるので最終的には人に聞いたり頼ったりすることになると思うのですが、どこまで個々人が自分自身で調べて解決できるかというところが大事だと思います。何かあったらすぐ頼るような状態では生産性が落ちます。&lt;br /&gt;「距離は近ければ近いほど良い」というのは物理的にも精神的にもです。物理的に近いほうがやりやすいというのは、極端な例で言えばお客さんが隣のフロアにいるとかです。何か困ったことが発生したときに、メールのやり取りや電話口でのやりとりで解決するより、走って行ってその場で手取り足取り説明したほうが断然早いしうまくいきます。精神的に近いほうがやりやすいというのは、仲がいい方がチームのムードも良くなるし対立が発生しづらいからです。個人的には、良いチームにはデルタフォースとかSASのような特殊部隊のイメージがあります。あのへんの特殊部隊の人が語るチームマネジメント本とか講演会とかあればいいなぁとか思います。&lt;/li&gt;&lt;li&gt;少数・精鋭・見知った仲でチームを結成する&lt;ul&gt;&lt;li&gt;少数になるようにする - 必要最小限の人以外を入れない&lt;/li&gt;&lt;li&gt;精鋭になるようにする - 可能であればそうするのがよいが、できる範囲でやるのであれば、同じ程度の実力の人を集めてチームにする&lt;/li&gt;&lt;li&gt;見知った仲になるようにする - まず知り合う、勉強会とかに行く、一緒に遊ぶ、共通の趣味嗜好を持つ、距離の近いお客さんを選ぶ&lt;/li&gt;&lt;/ul&gt;人を増やすのは比較的簡単ですが、減らすのは恐ろしく難しいです。人が増えると責任が薄まります。「俺がいなくてもどうにかなる」と気づいてしまうとヤル気が極端に下がりますし楽しくありません。もちろん、人が足りなくて毎日徹夜しないと追いつかないような状態になっているのはダメで、バランスが重要ですが、基本ほんの少しだけ足りない側に倒すほうが良いかと思ってます。&lt;br /&gt;チーム全体が精鋭になるようにするというのは、できるのであればそれが最も素晴らしいことだと思いますが、まぁ現実的に考えて難しいと思います。そんな手段があれば私がまず知りたいです＞＜ で、現実的な作戦としては、チーム全体の実力をできる限り均一化すると言うことが挙げられます。チームメンバーの実力にほとんど差がない状態が、一番チームメンバー個々の能力を最大限に発揮させ、責任感を最大限に発揮させることができると思うからです。一人だけ精鋭がいてもその人に負荷と責任が集中し、他の人はアイツがいるからと思ってしまいます。逆に一人だけおちこぼれるとみんながその一人のせいにして責任を放棄します。&lt;br /&gt;見知った仲になるようにするために、例えば社内で月一ピザでも食べながら勉強会をやるとか、 &lt;a href="http://twitter.com/torufurukawa"&gt;誰か&lt;/a&gt; の家に飲みに行くとか、お昼ごはんを一緒に食べるとか。ここが一番難しい気がしますが、一番大事なところだと思います。仲がよければちょっとやそっとのミスや負荷があっても許してあげられるようになります。逆に険悪になるとほんの少しのミスや負荷が許せなくなり、さらに事態が悪化します。&lt;br /&gt;ただし、仲が良いのと馴れ合うのは絶対に違うと思います。馴れ合い始めると新しい人が入ってこれなくなり、仕事に張りがなくなります。これもバランスですね。&lt;/li&gt;&lt;li&gt;開発チームとステークスホルダーが直接コミュニケーションできるようにする&lt;br /&gt;いくつかプロジェクトをやって気づいたことがこれで、開発チームとステークスホルダー（最終決定権保持者、各種画像リソースなどのリソース提供者）の距離が遠いとプロジェクトが失敗しやすくなります。距離が遠いというのは、間に仲介役 - たとえば営業の人だとか - が入るということです。人ほど信用ならない情報伝送経路はありません。必ず情報の劣化・嘘の混入・膨大な遅延が発生します。このような伝送経路を使うのをやめて、直接ステークスホルダーの人とSkypeでやり取りできるようになると、効率が格段によくなります。ミスも発生しません。&lt;/li&gt;&lt;li&gt;それでもどうしても何ともならないとき&lt;ul&gt;&lt;li&gt;人数が増えてしまった - チーム/責任範囲を分割して可能な限り少数にする、または別の仕事を取ってきてそちらにチームを分割する&lt;/li&gt;&lt;li&gt;スキルが低い人と一緒に仕事をする必要がある - 低い人の理解に全
