Blogs

Project Euler Problem66 ー ペル方程式って何?

in

Project Euler Problem66できたんだけど前回同様肝心なところは理解できずでなんかダウナー気味。Haskell勉強のお題ではじめたPEなので別に数学的なところがわからなくても一向かまわないわけだけどせっかく解くのだからもう少し理解したいなぁ。と痛切に思う次第。ということで、ペル方程式というのがあるらしく、

アプレンティスシップ・パターン

in
アプレンティスシップ・パターン ―徒弟制度に学ぶ熟練技術者の技と心得
アプレンティスシップ・パターン ―徒弟制度に学ぶ熟練技術者の技と心得 Dave H. Hoover Adewale Oshineye 柴田 芳樹

Amazonで詳しく見る by G-Tools

発展途上にあるエンジニアが熟練職人となるためのデザインパターン集。面白かった。自分的には、

  • 持続可能なモチベーション
  • 情熱を育む
  • 自分の地図を書く
  • ソースを活用する
  • 徹底的に調べる

あたりが重要かと。環境的に、最初の3つが厳しいし、技術的には後ろの2つ。あとは、ホント「練習・練習・練習」だねー。

Project Euler Problem64でとうとうカンニング

in

Project Euler再開してしばらくたちますがすでに壁にブチ当たってます。64問目にして、とうとうカンニングしちゃいました。だいたい、連分数って何よ!?っていう人間には難しすぎる。

というわけで、カツ丼食べながらHaskellで書いたのがこれ。

フィルタアニメーションのやり方がわからない...

テキストフィールドにフィルタをかけたるアニメーションを実装したいと思ったのですがなかなか思う通りにできません。みるくCocoaさんのサンプルにまさにコレ!というのがあったので早速試したのですが、デフォ0.25秒の動きが早すぎるのかどうしてもアニメーションしているようには見えませんでした。本家アップルののように、

CABasicAnimation *theAnimation =
  [CABasicAnimation animationWithKeyPath:@"filters.myGussian.inputRadius"];

theAnimation.duration            = 10;
theAnimation.fromValue           = [NSNumber numberWithFloat:5.0];
theAnimation.toValue             = [NSNumber numberWithFloat:0.0];
  
[[answerField layer] addAnimation:theAnimation forKey:@"filterAnimation"];

のように書き直しても動く気配なし。そもそもCore ImageとかCore Animationとか全然わかっていないのでコードの断片だけを拾い集めてきてもうまくいくはずもなく、アニメーションはあきらめて

if ([text wantsLayer])
{
  [text setWantsLayer:NO];
  [text setContentFilters:nil];
  return;
}
CIFilter *filter = [CIFilter filterWithName:@"CIGaussianBlur" keysAndValues:
                   kCIInputRadiusKey, [NSNumber numberWithFloat:2.5], nil];
[text setContentFilters:[NSArray arrayWithObject:filter]];
[text setWantsLayer:YES];

として、フィルタの適用をオン・オフだけするだけの実装にしてごまかして(実際これだけでも十分なんですが...)Core mage/Core Animation周りを勉強し直すことにしました。というわけで、これをポチ。

Core Animation for Max OS X and the iPhone: Creating Compelling Dynamic User Interfaces (Pragmatic Programmers) Core Animation for Max OS X and the iPhone: Creating Compelling Dynamic User Interfaces (Pragmatic Programmers)
Bill Dudney

Pragmatic Bookshelf 2008-10-15
売り上げランキング : 17174

Amazonで詳しく見る by G-Tools

アイコンポップアップボタン

in

Snow Leopardのアカウントアイコンの選択や、バージョンアップしたTarnsmit4にアイコンを選択するポップアップメニュー風のUIがあるのですが、

 Icon PopupMenu

子ノードには手を出すな(NSTreeController)

in

このところまたOutlineView+TreeControllerやってます。それでひとつ気づいたことをメモ。

"ツリーコントローラーにストアしているデータをすべてinsertしてもツリー構造にはならない"ということ。読み込んだ子ノードのデータをTreeControllerにinsertすると(親ノードの配下にも表示されますが)親ノードと兄弟のように表示されちゃいますね。ググってみたら、Fetch Predicateに”parent == nil"を指定する(cocoadev:NSTreeController)のが慣例みたいなんですが知りませでした。データの読み込みを確認しながらようやくわかった次第。要するに親ノードが持っている子ノードの展開はTreeControllerが内部で実行することになっているようでプログラムからは親ノードさえadd/insertしてやれば良いようです。当然バインドの場合でも上記の例のようにPredicateを指定する必要があるようです。(Appleの公式ドキュメントとしてどこかに書かれているのかな?)

NSManagedObjectContext *moc = [self managedObjectContext];
NSFetchRequest *fetch = [[[NSFetchRequest alloc] init] autorelease];
NSArray* sortDesc = [NSArray arrayWithObject:
  [[[NSSortDescriptor alloc] initWithKey:@"orderNo" ascending:YES] autorelease]];

[fetch setEntity:
  [NSEntityDescription entityForName:@"ChildNodeEntity" inManagedObjectContext:moc]];
[fetch setPredicate:[NSPredicate predicateWithFormat:@"isLeaf == 0"]];
[fetch setSortDescriptors:[self sortDesc]];

NSError *err     = nil;
NSArray *results = [moc executeFetchRequest:fetch error:&err];
if ((err) || (results == nil))
{
  [NSApp presentError:err];
  return;
}

NSUInteger index = 0;

for (ChildNodeEntity *node in results)
{
  [treeController insertObject:node atArrangedObjectIndexPath:
    [NSIndexPath indexPathWithIndex:index]];
  index = index + 1;
}

まあ、実際にやりたかったのはノードの表示順を一定に保つことでCocoaDevのリンクnstreecontroller-and-core-data-sortedにもあったようにノードの中になんらかの方法で順序を示す数値を仕込んでおけばOK。子ノードの展開はTreeControllerお任せになるのでSortDescriptorをバインドする必要もあります。ロード時に特別の処理がなければ僕のコードのようにガリガリコードを書くのは不作法で、やっぱりバインドしたほうがスマートですね。

ちゃんと考えた方がいいというハナシ。

in

今日はHDDがやばそうなサーバのバックアップ機のセットアップ。大方できあがって最後CPANモジュールのインストールの段になってどうしてもインストールできません。どうやら全部プロキシでハネられているようなんですが...いや絶対間違ってないぞ!と思いつつ格闘するも2時間。とうとう諦めて、本番サーバのConfig.pmをもってきてdiff。

# diff Config.pm Config.pm_BAK
14c14
<   'ftp_proxy' => q[http://xxx.x.x.xxx:8080/],
---
>   'ftp_proxy' => q[ftp://xxx.x.x.xxx:8080/],

いや、ftp_proxyなんだから...ftpでしょ?あー疲れた一日。

EVP_*系APIでのBlowFish実装

パスワードを保存するアプリを作るため以前使ったことのあるBlowFishのmanを読み直していたら、BF_*系の関数を直接使うんじゃなくてもっと高レベルのEVP_EncryptInitとかを使いなよって書いてあったので忠告に従いこちらを使うべく調べてみました。BF_*系と違うのは暗号・復号に際して必要な情報を追跡するためのコンテキスト情報EVP_CIPHER_CTXを維持していく必要があるのが大きな違いになります。処理は

  1. 暗号コンテキストの初期化
  2. 暗号化方式の決定と初期化
  3. 暗号・復号処理
  4. 暗号コンテキストの解放

といったフローでそれほどステップは多くないカンジ。まず、暗号コンテキストの初期化は

Core Dataのマイグレーション(手動編)

in

既存のマッピングで対応できないような場合、NSEntityMigrationPolicyを拡張してカスタマイズできることはわかったのですがドキュメントを読むだけではいまひとつピンとこなかったので実際にやってみました。トライしたのは下記のアドレス帳モデルの変換。とりあえず、v1のモデルで固定・携帯の2つの電話を持つ桃太郎、携帯電話のみを持つ浦島太郎、電話は持たない一寸法師のアドレス帳データを作成しこれをv2モデルに変換します。マイグレーションの骨子は、

  1. 電話を持たない人はそのまま新しいAddressBookエンティティにマッピング
  2. 電話を持つ人はPhone1/Phone2をPhoneBookエンティティにマッピング

の2点。1に関しては通常のマッピングで対応し、2に関してマイグレーションポリシーを拡張します。

まず、v1のAddressBookエンティティにあるphone1とphone2をPhoneBookエンティティに移行するため新しいマッピングを適当な名前で作成します。ここではAddressBookToPhoneBookという名前のマッピングモデルを作成しました。ソースにはAddressBook、デスティネーションにはPhoneBookを指定します。また、電話を持たないAddressBookインスタンスはPhoneBookへのマッピングは不要なのでフィルタ述語に

Core Dataの自動マイグレーション

in

Core Dataの使い始めの頃、マイグレーションには散々苦労したのですがいつの間にか自動マイグレーション機能なんかができていてこれがいたって簡単でした。手順としては

  1. 新しいモデルの作成
  2. マッピングモデルの作成
  3. 自動マイグレーションの指定

の3ステップだけ。

まず新しいモデルを作成する場合ですが、既存のモデルエディタに直接修正を加えるのではなくて、[設計]-[データモデル]-[モデルバージョンを追加]で新しいモデルを作成します。これで、既存のモデルをベースに新しいモデルが作成されますので新しいモデルに必要な修正を加えます。モデルの作成が終了したら[設計]-[データモデル]-[現在のバージョンを設定]で、新しく作成したモデルをカレントモデルに設定します。これが第一段階。

次はマッピングモデルの作成。ある意味、これがマイグレーションの本体となります。[新規ファイル追加]-[リソース]-[マッピングモデル]で新しいマッピングモデルを作成しますが、ここで「ソースモデル」と「デスティネーションモデル」を指定します。「ソースモデル」が既存のモデル、「デスティネーションモデル」が先に作った新しいモデルファイルになります。

このマッピングモデルに(旧)エンティティ(のどのプロパティ)が(新)エンティティ(のプロパティ)にマッピングされるかを記述していくわけです。作成直後の状態では、名前を元にマッピングが作成されているのでこれをベースに必要なマッピングを記述していけばホント簡単にマイグレーションできちゃいます。マッピングは新旧エンティティが一対一にならなくとも良くて、いくつもマッピングを作成することができます。例えばPredicateを指定すれば、ある(旧)エンティティAのうち、条件xに合致するデータは(新)エンティティA'にマッピング、条件yに合致するデータは(新)エンティティA''にマッピングなどということができるわけです。

最後は、コーディネーターに自動でやってねってお願いするのを忘れずに。

NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
    [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
    [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
[persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType 
                            configuration:nil 
                            URL:url
                            options:options
                            error:&err]);

たったこれだけで、エンティティとその属性(もちろん関連も)移行してしかも殆どノーコード。モデルのバリデーション(例えば新しく追加した属性がオプショナルでない場合など)に注意すれば実にスマートな移行ができます。実際のところ、単なる属性追加だけとか非オプションをオプションに変えるだけとかだったらマッピングモデルの作成すら省略することができるなんてサービスしすぎな気がしなくもないです。

さらにはNSEntityMigrationPolicyをオーバーライドしてさらに複雑なマイグレーションのための手段もあるので次回はもう少し複雑なパターンを書いてみようと思ってます。

あっ、v10.4では...ちょっとね、ダメみたいです。悲しいことに。

(参考)Introduction to Core Data Model Versioning and Data Migration Programming Guide

NSTaskは~/Library/Apprication\ SupportでもOK

in

NSTaskでスクリプトを実行する時、${HOME}/Libray/Apprication\ Supportでも実行できるか不安だったので念のため試してみたところちゃんと実行できました。いや、単にパス名にスペースが含まれているから実行できるか不安だっただけですが...(MacOSXには"Program\ Files"的なものはないかと思っていましたがあるんですね。)

- (void)setCurrentDirectoryPath:(NSString *)pathで移動してやればOK。Cocoaはやっぱり! - Perlスクリプトを実行するに詳しいです。これまでtemporaryディレクトリなんかを使ってやっていたんですが、ここを使えば競合なんかの心配が限定できるのでじゃかじゃかやれます。Core Dataのデフォルト保存パスがここになっていることでようやくこのテに気がつきました。日本語を含むディレクトリでも正しく起動できました。ま、カレントディレクトリを変えちゃうんだから当たり前なんだけど、Winじゃ"Program\ Files"とか"My\ Document"とか痛いことあるし...

XCodeで外部エディタが起動できないとファイルが削除されたことになる件

XCode上でLocalizable.stringsを編集しようとすると、「ファイルは移動または削除されました」と言われて編集できないという事態が昨日突如発生して困っていたのですが、ようやく解決しました。

なんのことはない、Localizable.stringsの編集に指定していた外部エディタ(Smultron)を削除してしまっていたためでした。開発のストップしてしまったSmltronの代わりにFraiseをインストールした際、Smultronは削除したのですが、指定していた外部エディタが起動できないとXCodeは「ファイルがないぜ!」と言うようです。デフォルト状態戻したらちゃんと編集できるようになりました。エディタがないからってファイルが削除されたかのメッセージはどうかな?Finder上ではちゃんと存在するのに。

こんなメッセージだとXCodeが壊れたのかと思ってしまいます。もう少しで再インストールするとこでした。なんでLocalizable.stringsをなんで外部エディタ編集にしていたかっていうと、ATOKがXCodeで使えないって問題しかたなくそうしていたわけですが意外なところで足下救われました。まったくくだらないところで時間を使いました。(;_;)

しかし、ちょうど良いタイミングでATOKのほうもパッチがでたみたいだしとりあえず良かった。徒労感満々ですが....

ガベージコレクションに気をつけて

in

先日作成したftpのサンプルアプリですがNSInputStream/NSOutputStreamのretain/releaseを書いてないのでGCオプションをなしにするとエラーとなります。自分ではこのオプションを変更した記憶はないのですが、なにせv10.4対応アプリを作成中なので色々いじっているうちに、なぜかDebugバージョンは[GCC_ENABLE_OBJC_GC, -fobjc-gc-only]で、Releaseバージョンでは非対応になってしまったようです。せめて逆なら良かったのですが、こういうオプションは構成毎に連動してくれればいいのに。と思ったりもしますがもちろんそれくらい自分で管理しないとダメ。とにかく、これにハマると、Bad AccessやらSelectorがないよ!とかいろんなエラーが出て、迷いに迷うので要注意です。

Cocoaでアプリケーション名をローカライズするには...

in

Cocoaでリソース関連をローカライズするにはIBで日本語なら日本語のリソースを作ってやればいいのだけれどアプリケーションの名称はこれではローカライズできません。

スクリーンショット

CocoaでFTPする方法

in

FTPのput機能が必要になる要件があってConnectionKitを使うツモリで調べてたんですがこのFrameworkのサンプルがビルドできなくてアレだったし、Applのサンプルをみたら意外と簡単そうだったので自前で実装してみました。

  1. putするローカルファイルのNSInputStreamを用意する
  2. リモート側に出力するためのNSOutputStreamを用意する
  3. RunLoopのdelegateメソッドを実装する
  4. ストリームの後始末

といった手順になります。

コンテンツの配信