2011年7月26日火曜日

crashログの備忘録

クラッシュしたスレッドがフレームワークのみの場合がある。
その場合、そのフレームワークで呼び出されるdelegate関数が一番怪しい。

2011年5月28日土曜日

FacebookにiOSプログラミングページを作成中

Objective-C編 : http://docs.com/C32O
開発環境編 : http://docs.com/C327
APP作成編(作成中) : http://docs.com/CN01


Facebookの使い方が未だよく判らないけど
iOSプログラミングというfacebookページを作って
情報をまとめ中。

2011年4月24日日曜日

開発プロセスを推進するほど生産性は下がる

ソフトウェア開発を工業化しようとして、様々な開発プロセスが提案されてきた。
主目的は管理者が開発をコントロールするためなのだろうが、
そもそも論として前提が間違っている気がする。

「誰でも頑張ればプログラムが作れる」

そのための冗長な作業が増大し、
生産性の高い人達がプログラミングする時間を奪っていく。

実は人材育成には有効でも生産性は相当落ちている。
その人材が生産性の高い人に育つ、という前提なのだが…

**********
積み木は三歳児でも使えるが、作るには職人技が必要である。
英文法は理解しているが英会話はできない。
・・・

2011年4月20日水曜日

MPMusicPlayerControllerの注意点

iPodライブラリの再生で使うMPMusicPlayerControllerにはバグっぽい注意点がある。

停止させた時のステータスが、
iPhoneではMPMusicPlaybackStateInterrupted
iPadではMPMusicPlaybackStatePaused
と異なっている。
いずれもiOS4.3だけど、iPadの方が正しい気がする。

2011年3月17日木曜日

iOSでの印刷

大雑把に次の2つの手順となる。
1.UIPrintInteractionControllerを起動する。
2.UIPrintPageRenderer のサブクラスで印刷処理をする。

【1.について】
イベント発生時(通常はメニュー選択)に呼び出される関数を作成する。
- (IBAction)printPage:(id)sender
{
 UIPrintInteractionController *controller = [UIPrintInteractionController sharedPrintController];
  void (^completionHandler)(UIPrintInteractionController *, BOOL, NSError *) =
 ^(UIPrintInteractionController *printController, BOOL completed, NSError *error) {
  if(!completed && error){
   NSLog(@"FAILED! due to error in domain %@ with error code %u", error.domain, error.code);
  }
 };

 // UIPrintInfo の作成
 UIPrintInfo *printInfo = [UIPrintInfo printInfo];
 printInfo.outputType = UIPrintInfoOutputGeneral;
 printInfo.jobName = [NSString stringWithFormat: @"job title"];
 printInfo.duplex = UIPrintInfoDuplexLongEdge;// 両面印刷
 printInfo.orientation = m2pView.frame.size.width < m2pView.frame.size.height ?
  UIPrintInfoOrientationPortrait : UIPrintInfoOrientationLandscape;// 用紙方向を画面の方向と同じする
 controller.printInfo = printInfo;
 controller.showsPageRange = YES;// 複数ページ

 // UIPrintPageRendererのサブクラスを作成
 MyPrintPageRenderer *myRenderer = [[MyPrintPageRenderer alloc] init];
 myRenderer.jobTitle = printInfo.jobName;
 myRenderer.m2pView = m2pView;//描画用のコントロールを渡しておく
 controller.delegate = myRenderer;//印刷時のdelegate関数はMyPrintPageRendererに記述
 // ビューフォーマッターとやらの定義も必要らしい
 UIViewPrintFormatter *viewFormatter;
 viewFormatter = [self.m2pView viewPrintFormatter];
 [myRenderer addPrintFormatter:viewFormatter startingAtPageAtIndex:0];
 controller.printPageRenderer = myRenderer;
 [myRenderer release];
 // 印刷ダイアログ表示(印刷ボタンを押せばMyPrintPageRendererのdelegate関数が呼ばれる)
 if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
  [controller presentFromBarButtonItem:bbiPrint animated:YES completionHandler:completionHandler];  // iPad
 else
  [controller presentAnimated:YES completionHandler:completionHandler];  // iPhone
}
【2.について】
Appleが提供するサンプルコードのMyPrintPageRenderer.mがほぼ流用できる。
印刷領域は、ヘッダー・コンテンツ・フッターの上中下3分割となっている。
以下をページ単位に描画すればOK.
- (void)drawHeaderForPageAtIndex:(NSInteger)pageIndex inRect:(CGRect)headerRect;
- (void)drawContentForPageAtIndex:(NSInteger)pageIndex inRect:(CGRect)contentRect;
- (void)drawFooterForPageAtIndex:(NSInteger)pageIndex inRect:(CGRect)footerRect;

2011年3月6日日曜日

The end のリードギター

以下へ移動
http://www.facebook.com/pages/MID2PRN/128787497224101?sk=app_235501026504227

人月という単位はそれを理解出来ない人に対して使われる

一人で一ヶ月かかる作業は10人ですれば3日でできる。
ベテラン1人月と素人1人月は同じ作業量である。

論理的に反論出来ない人を押さえ付けるには便利な言葉である。

(追記)
プログラマーの場合、1人月の個人差が大きく、給与の比では収まらない。
数学の試験で直ぐに解答してしまう人もいれば、
一生かかっても解けない人がいるのと同じである。

2011年2月19日土曜日

Sqlite3でDBを結合する方法

openできるDBはひとつだけなので
結合するDBはATTACHで指定する。

まず以下の関数を作成する。

- (void)Attach:(sqlite3 *)hDB DB:(NSString *)dbName
{
NSString *attachSQL = [NSString stringWithFormat: @"ATTACH '%@' as %@",[[NSBundle mainBundle]
                                    pathForResource:dbName ofType:@"db"],dbName];
const char *sql_stmt = [sql UTF8String];
char *errMsg;
if (sqlite3_exec(hDB, sql_stmt, NULL, NULL, &errMsg) != SQLITE_OK)
 NSLog(@"AttachSQL failed : %s",errMsg);
}

使い方はこんな感じ(エラー処理は略)
sqlite3 *contactDB;
const char *dbpath = [[NSString stringWithFormat: @"ATTACH '%@' as %@",[[NSBundle mainBundle]
                                    pathForResource:@"mainDB" ofType:@"db"],dbName] cString];
sqlite3_open(dbpath, &contactDB);
[self Attach:contactDB DB:@"secondDB"];
querySQL = [NSString stringWithFormat: @"SELECT a.id, b.Comment
                   FROM mainDB a, secondDB b
                   WHERE a.id=b.song AND a.key=\"ABC\""];
const char *query_stmt = [querySQL UTF8String];
sqlite3_stmt    *statement;
sqlite3_prepare_v2(contactDB, query_stmt, -1, &statement,NULL);
sqlite3_step(statement);
・・・

2011年2月9日水曜日

Matchboxのリードギター

全曲バイブルのボツネタですが、
この曲はハンブルク時代はジョンがボーカルとリードギターを担当していたようだ。
デビュー後のラジオ番組ではリンゴのボーカル曲としてジョンがレパートリーから選曲したのだろう。
この時点ではリードギターは未だジョンの演奏と思われる。
レコード用に正式なレコーディングをするに当たり何故かリードギターがジョージになっている。

2011年1月31日月曜日

周波数解析と楽器の特定

全曲バイブルの作業中、ヘフナーとリッケンバッカーの特徴を示すために周波数解析を行った。すると、ヘフナーは1オクターブ上の音程であるかのようなグラフを示していた。ここで自身でも初めてセミアコとソリッドボディーの特徴を理論的に理解することができた(もちろん楽器メーカーであれば当然の如く所有している情報だろう)。
音は複数の倍音で構成されるが、セミアコのボディは低い音を維持するのが難しいらしく、基音は直ぐに減衰し第2倍音以上の音が音色の中心となる。これがヘフナーが軽い音に聴こえる主因である。

同様に、カジノはストラトやレスポールに比べて軽い響きになっている。
このことから、Day Tripper/Taxman/Paperback Writerのリードギターはセミアコ系の楽器であると推測できる(残念ながらサウンド解説には反映していないが)。Day TripperはグレッチかES-345、TaxmanとPaperback Writerはポールによるカジノの演奏だろう。

なお、I Feel Fineの項で示した通り、音の歪みは高次倍音の増加で生じる現象である。歪んだ音の高域をイコライザーでカットしてみれば元の楽器のニュアンスが聴こえて来るはずである。

2011年1月25日火曜日

能力主義と言う人に限って能力の逆転現象を生み出す

部下がニュートンとアインシュタインだった場合、
正しく評価できる人がいるだろうか。
確実なのはどちらも自分より遥かに優れているということ。
でも自分と立場を入れ替えようとする上司はいない。
一度逆転現象が起こった組織は中々立ち直れない。

仕事は効率化するほど評価は下がる

効率的に仕事をすると次のように評価される。
・他の人より簡単な仕事だったらしい
・Webでも見て情報収集しようとしても『怠けている』
・定時に帰ろうものなら『協調性が無い』

遅れやトラブルを解決してこそ評価されるのであり、
トラブルを未然に回避しながら予定通り進めても
自己満足しか得られない。

2011年1月23日日曜日

証明書の期限切れ

証明書の期限が切れたとき、更新はオーガナイザで簡単にできるようになったけど、
そのままビルドしても以下のエラーがでる。
[BEROR]CodeSign error: Certificate identity 'iPhone Developer: (my name)
(SFQA882WV4)' appears more than once in the keychain. The codesign
tool requires there only be one.
この時は、アプリケーション/ユーティリティ/キーチェーンアクセスを起動して、
古い証明書を削除すれば直る。

2011年1月10日月曜日

iPodライブラリの選択画面をナビゲーションさせる方法

以下のコードで可能。
   MPMediaPickerController *picker = [[MPMediaPickerController alloc] initWithMediaTypes: MPMediaTypeMusic];
   picker.delegate      = self;
   picker.allowsPickingMultipleItems = NO;
   picker.prompt      = NSLocalizedString (@"Select song", @"");
   [[self navigationController] pushViewController:picker animated:YES];
   [picker release];
選択の処理には以下のデリゲート関数を定義する。
- (void) mediaPicker: (MPMediaPickerController *) mediaPicker didPickMediaItems: (MPMediaItemCollection *) mediaItemCollection;
- (void) mediaPickerDidCancel: (MPMediaPickerController *) mediaPicker;

※残念ながらiOS7では使えなくなったようです。

PopoverControllerでナビゲーションする方法

以下を定義しておく。
UIPopoverController *myPopoverController;

// MyTableView をPopoverControllerで表示するコード
// このときにUINavigationControllerを使う!
 if( isIPad() ) {
  if (!myPopoverController) {  
   MyTableView *controller = [[MyTableView alloc] initWithNibName: @"MyTableView" bundle: nil];
   controller.delegate = self;  
   UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:controller];
   [controller release];
   myPopoverController = [[UIPopoverController alloc]initWithContentViewController:navigationController];  
   myPopoverController.delegate = self;  
   [navigationController release];
  }  
  if(!myPopoverController.popoverVisible) { // visible でない場合  
   [myPopoverController presentPopoverFromBarButtonItem:navigationBar.topItem.leftBarButtonItem  
            permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];  
  }  
 } else {
  MyTableView *controller = [[MyTableView alloc] initWithNibName: @"MyTableView" bundle: nil];
  controller.delegate = self;
  controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
  UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:controller];
  [controller release];
  [self presentModalViewController:navigationController animated: YES];
  [navigationController release];
 }
後はMyTableView側で以下の制御をするだけ。
<ナビゲーション>
 [[self navigationController] pushViewController:NewController animated:YES];
<復帰>
 [[self navigationController] popViewControllerAnimated:YES];