Displaying posts written by

tkykmw

who has written 197 posts for へびにっき.

External Objectを使ってIBOutletからNibファイル外のオブジェクトに接続する

External Objectを使うことで、Nibファイル外のオブジェクトに対してIBOutletで接続できる。ちなみにこの機能はMac OS Xでは使用できず、iOSでのみ使える。 …… たとえばあるカスタムビューからモデルのインスタンスを参照したいとする。このビューでは常にモデルの状態を反映した表示を行いたいので、インスタンス変数にモデルへの参照を保持しておきたい。 ビューの生成・初期化をプログラム中で行うなら、initWithModel:のような初期化子を用意しておけば済む。しかしビューをNibファイルから生成する場合は初期化時にモデルを参照することができない(モデルは普通Nibファイルで生成しないので)。仕方がないのでモデルのインスタンスだけはUIViewControllerのviewDidLoadでビューに代入して、専用の初期化メソッドを呼び出すなどするしかない。これは非常に面倒だし忘れやすい。 – (void)viewDidLoad { [super viewDidLoad];   //プロパティに代入してから表示を更新。面倒くさい _customView.model = _model; [_customView update]; } そこでExternal Objectの出番である。このオブジェクトはNibファイル外の既成のオブジェクトに対するPlaceholderとして機能する。ちょうど自由な名前をつけられる「File’s Owner」だと考えれば良い。 使い方は次のようになる。まずカスタムビューの.hファイルで、モデルに対するOutletを設定しておく。 @interface CustomView : UITableViewCell { Model *_model; }   @property (nonatomic, retain) IBOutlet Model *model; モデルを使った初期化処理は、その他の初期化処理と同じくawakeFromNibの中に書くことができる。 – (void)awakeFromNib { [super awakeFromNib];   //モデルのデータを使って表示を初期化する _textField.text = _model.name; } 続いてxibファイルを開いてExternal Objectの設定を行う。Libraryの中から「External Object」を選んでObjectsの欄にドラッグアンドドロップすると、Placeholdersの欄にオブジェクトが追加される。 追加されたオブジェクトを選択してIdentity [...]

Eee PC 1015PEMにUbuntu 10.10インストール(無線LANの問題解消)

追記(11.10用) 下記の設定を行った状態で11.10にアップデートしたら無線LANが認識されなくなった。/etc/modprobe.d/blacklist.conf で次の1行をコメントアウトして再起動したら復活した。 #blacklist rt2800pci … ASUSのネットブックEee PC 1015PEMを買った。標準で入っていたWindows 7 Starterを使う気はさらさらなかったので、リカバリ領域をUSBメモリにバックアップした後、HDD丸ごと使ってUbuntuをインストールした。もうすぐ11.04が出るのだが、とりあえず10.10を選択。 1015PEMには光学ドライブはないのでインストールはUSBメモリから。手順はUbuntu公式の「Netbook」のダウンロードページに書いてある。まずWindowsでUniversal USB Installerをダウンロードして、次にUbuntu Japanese Teamのサイトから10.10 Desktop 日本語Remixのisoイメージを落とし、Universal USB Installerを起動してUSBメモリに書き込んだ。 あとはUSBメモリを刺して起動時にBIOSでboot deviceを指定、画面に従ってインストールするだけ。ちなみにこのときUSBメモリから直接起動して動作をテストすることもできるが、その動作は実際にインストールしたときの動作とは必ずしも一致しないことに注意。私の場合、この方法で起動すると無線LANが全く繋がらなかったり、日本語入力が使えなかったりした。 インストール自体は30分ほどで終了。早速無線LANに繋いでソフトウェアアップデートをかけるが、どうもネットワークの速度が遅い。pingを打ってみると30%〜ほどのパケットが欠落している。有線LANに繋ぎ変えると正常なので、明らかに無線LANがおかしい。Windows 7で使ったときには正常だったから、問題は無線LANアダプタのドライバだろうと当たりをつけて調査開始。 結論から言うと、次の操作を行うことで解消した: /etc/modprobe.d/blacklist.conf に以下の内容を追記して、マシンを再起動。 blacklist rt2800pci blacklist rt2800lib blacklist rt2800usb blacklist rt2x00usb blacklist rt2x00pci blacklist rt2x00lib 問題を解消するにあたってはこのページが非常に役に立った。 Ubuntu 10.04 LTS でEeePC 1015PEMで無線LANを使う(Ralink RT3090) – Ubuntuスタイル まずlspciコマンドを実行してみると、確かにRaLink社のRT3090というアダプタが搭載されているのが確認できた。そこでRaLink社のサイトを見に行ったところ、Linux用のドライバが配布されていたので、早速「RT3090」用のファイルをダウンロードした。zipファイルを展開して中を見てみると、このドライバは「RT2860STA」という名称だと判明した。 ここでインストールする前に念のため lsmod | grep rt で現在読み込まれているドライバを確認してみたところ、既にrt2860staは読み込まれている、つまりUbuntu [...]

nginxでメンテナンス中画面を表示する

どのURLにアクセスされてもステータスコード503を返して /home/www/maintenance.html を表示する設定。 server { server_name your.hostname; error_page 503 /maintenance.html; location / { return 503; } location = /maintenance.html { root /home/www; } } 同等の設定をApache(>=2.2)で書くと次のようになる。 <VirtualHost *:80> ServerName your.hostname DocumentRoot /home/www   RewriteEngine On RewriteCond %{REQUEST_URI} !=/maintenance.html RewriteRule .* – [R=503]   ErrorDocument 503 /maintenance.html </VirtualHost>

ImageStore(改造版)を使って画像を非同期ダウンロードする

ImageStoreはiOSで画像を非同期ダウンロードするためのObjective-Cライブラリです。Satoshi Nakagawaさんがオープンソースのライブラリとして公開されています(New BSDライセンス)。手軽に使えて非常に便利なライブラリなのですが、そのままアプリに組み込むには少々難があります。 ダウンロードをキャンセルする手段がない ImageStoreのインスタンスを破棄する以外に、キャッシュをクリアする方法がない 正常に画像がダウンロードできたかどうか判定する術がない 1がないので、ダウンロード中に画面移動が発生したりすると容易にクラッシュします。2がないので、随時キャッシュを消して再ダウンロードしたり、メモリ不足時にキャッシュを削除したりといったことができません。3のため、サーバが404を返した場合等にはリクエストが無限ループしてしまう危険があります(ImageStoreの中に含まれるサンプルアプリではそういう仕様になってしまっています)。また画像が取得できなかった時に代替画像を表示するといった処理も実装できません。 そこでオリジナル版からforkして、これらの不具合を解消した改造版を作りました。 https://github.com/tkyk/imagestore (4月6日追記: 私の改造版とは使い方が異なりますが、本家ImageStoreでも同等の修正が行われました) ImageStoreクラスには4つのメソッドが増えました。どんなメソッドかは名前から想像がつくと思います。 – (void)cancelAllDownloads; – (void)cancelDownloadFromUrl:(NSString*)url; – (void)clearAllCaches; – (void)clearCacheForUrl:(NSString*)url; ImageStoreDelegateにも新たにメソッドが宣言されています。 – (void)imageStoreDidFailNewImage:(ImageStore *)sender url:(NSString *)url fallbackImage:(UIImage**)anImage; 使い方 UITableViewの各Cellに画像を表示する処理を例に、使い方を説明していきます。現実のiPhoneアプリの開発で良くあるパターンだと思います。 まず tableView:cellForRowAtIndexPath: で UITableViewCell の表示を更新するときにgetImageを呼び出します。画像が既にキャッシュされていればその場でUIImageのインスタンスが返却され、キャッシュがなければnilが返されて非同期の画像ダウンロードが開始されます。 – (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell; //…略…   //このindexPathに対応する画像のURL NSString *imageURL = [self getImageURLAtIndexPath: indexPath];   //getImageにURLを渡す cell.imageView.image [...]

iOS開発におけるパターンによるオートマティズム レビュー

新しい知識を与えてくれる本ではない。ページ数も200ページ弱しかない。ある程度のiOS開発経験者なら、初めて知る内容はほとんど無いだろう。しかし数多の知識よりも遥かに価値ある知見を提供してくれる本だ。 以前も書いたが、iOS初学者が入門書を終えた後で「知識」を増やすには、下手に本を読んだりWebを漁ったりするより、Appleが提供している公式のプログラミングガイドを読むのが一番いい。フレームワークの各コンポーネントにどんな機能があり、どんな使い方があるか、他のどんな文書より網羅的に知ることができる。 しかし100通りのやり方を知っていても、実際にアプリケーションを作る時には、その中からたった1通りのやり方を選ばなければならない。その時その状況にあったベストなやり方を選ぶのはとても難しい。単に知識を増やすだけでは不十分で、フレームワークの設計思想や、作ろうとしている機能の性質についての深い理解、そして何より多くの経験・試行錯誤に基づく知見が必要だ。 この本が提供しようとしているのがまさにそれである。「いろいろ他の方法も考えられるが、この方法がベストである。なぜなら…」と本書は説く。プログラマの三大美徳としての”傲慢さ”に溢れた本である。著者を深く尊敬せずにはいられない。 というわけで、私もその傲慢さに倣って、いくつかの内容について強化/改善案を提案したい。 メモリ管理のパターン[4]について この本では「インスタンス変数はretainし、releaseした後は常にnil代入する」という原則が貫かれている。とても合理的で分かりやすく、早速真似させてもらったのだが、deallocメソッドの中で同じ形の式が繰り返されるのがちょっと見苦しい。 – (void)dealloc { [_identifier release], _identifier = nil; [_title release], _title = nil; [_link release], _link = nil; [_itemDescription release], _itemDescription = nil; [_pubDate release], _pubDate = nil;   [super dealloc]; } Xcodeの補完機能は優秀なので、こういった繰り返しを書くこと自体はさほど苦ではないのだが、個人的に見た目が(生理的に)我慢できないので、次のようなマクロを書いた。 #define DESTROY(x) [x release], x = nil   – (void)dealloc { DESTROY(_identifier); DESTROY(_title); DESTROY(_link); DESTROY(_itemDescription); [...]

iOSでJSONを扱う(YAJL使用)

環境: iOS 4.3, Xcode 4 iOS(iPhoneアプリ)でJSONを扱うライブラリとしてはJSON Frameworkが有名だが、敢えてyajlのObjective-Cバインディングを使ってみた。 インストール プロジェクトページののREADMEに従ってインストールする。 1. githubのダウンロードページから YAJLiOS-{version}.zip をダウンロードして、展開してできた YAJLiOS.framework ディレクトリを自分のプロジェクトのFrameworksの中にドラッグ&ドロップして追加する。このとき『Copy items into destination group’s folder (if needed)』にチェックを入れておく。 2. XcodeでBuild Settingsを開き、「Other Linker Flags」に -ObjC と -all_load の2つのフラグを追加する。 3. JSONを使いたいファイルでヘッダファイルをimportする。 #import <YAJLiOS/YAJL.h> ドキュメントのインストール ドキュメントは http://gabriel.github.com/yajl-objc/から参照できるが、Xcodeにインストールすることもできる。 1. githubのダウンロードページからYAJL-{version}.docset.tgzをダウンロードして、展開してできたYAJL.docsetを ~/Library/Developer/Shared/Documentation/DocSets/ の中にコピーする(このディレクトリはデフォルトでは存在しないので、自分で作成する)。 Xcodeを再起動すると、HelpのDocumentationから参照できるようになる。 使い方 JSONのデコード NSData および NSString として表現されたJSONは yajl_JSON: メソッドで直接デコードできる。 NSError *error; id result [...]

Xcode4でiOSのドキュメントが消えてしまった場合の対処法

Xcodeのバージョンを4に上げた後、iOSのリファレンスが参照できなくなった。 復活させるにはメニュー「Xcode」→「Preferences」→「Documentation」を選んで、「iOS 4.3 Library」の右側に表示されている「GET」ボタンを押すと、435MBほどのドキュメントがダウンロードされ、使用可能になる。

『基礎からのiOS SDK』正誤情報

『基礎からのiOS SDK』の中で間違っている・問題のある部分をまとめました。今までこのブログに書いてきた内容と大半は重複しますが、可能な限り客観的に問題があると証明できるものだけを選び出しています。書籍サイトの問い合わせフォームから同一内容を送っておいたので、いずれは公式に正誤情報としてまとめられるかもしれません(その際にはこのエントリは削除します)。 全文は「続き」からどうぞ。

jQuery 1.5の新機能: jQueryのサブクラスが作れるようになる

jQuery 1.5 beta1 のリリースノートを見ていたら面白そうな機能があったので紹介。 1.5正式版では jQuery.sub という名称に変更になったので、本文およびサンプルコードを修正しました。 jQuery.sub() でjQueryのサブクラスを作ることができる var MyjQuery = jQuery.sub(); 作成したサブクラスには独自のメソッドを定義することができる。定義の仕方、使い方は通常のjQueryと全く同じ。 MyjQuery.fn.writeHello = function(){ this.text(’Hello World’); };   MyjQuery(’p').writeHello(); 通常のjQueryメソッドはサブクラスでもそのまま使える。サブクラスを作った後に追加したメソッドも使えるので、プラグインによる拡張と組み合わせても大丈夫。 MyjQuery(’div’).css(’border’, ’1px red solid’).writeHello();   //元のjQueryを拡張 jQuery.fn.pluginMethod = function(){ alert(’OK’); };   //OK MyjQuery(’.klass’).pluginMethod(); 逆にサブクラスで追加したメソッドは元のjQueryからは見えないので、プロジェクトやプラグインに固有なメソッドを定義したり、元のjQueryにあるメソッドを上書きしたりといったことが安全にできる。 // text メソッドを上書きする MyjQuery.fn.text = function(val) { var orig = jQuery.fn.text; if(typeof val === "string") { return [...]

Functionコンストラクタと関数式(function expression)の違いなど

JavaScript Patterns 2章ではevalの代替としてFunctionコンストラクタを使う方法が紹介されています。Functionコンストラクタは、普通にJavaScriptを書いている分にはなかなか使うことがないので、馴染みがない人も多いだろうと思います。そこで関数式との比較を中心に簡単にまとめておきます。 Functionコンストラクタは、関数オブジェクト(つまりJavaScriptにおける関数)を作るためのコンストラクタです。文字列をJavaScriptコードとして扱えるという点ではevalにも似ていますが、戻り値は普通の関数なので、その他の方法で作った関数と全く同じ使い方ができます。 var funcObj = new Function(’x', ‘y’, ‘console.log(x + y);’);   //普通に呼び出す funcObj(1,2); // 3   //コンストラクタとして使ってみる funcObj.prototype.hello = function(){ console.log(’World’); }; (new funcObj(4,5)).hello(); // ‘World’ ちなみにコンストラクタではなく関数として呼び出した場合は、コンストラクタとして呼び出した場合と同じ結果になります(仕様上そう規定されています)。よって以下の2つは同じ意味になります。 var funcObj1 = Function(’x', ‘y’, ‘console.log(x + y);’), funcObj2 = new Function(’x', ‘y’, ‘console.log(x + y);’); この形、関数式にnew演算子を適用した場合と見た目が似ていますが、全く意味が違うということに注意してください。 // 関数式で関数を作る var funcObj = function(){}   // [...]