WEBアプリケーション研究室 開発ノート TOP

WEBアプリケーション研究室 開発ノート 2009年10月

スポンサーサイト

-------- --:--

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

    このエントリーをはてなブックマークに追加


//selectedListはNSMutableArray
for(NSInteger row as selectedList)
{
//ここでなにか
}
selector element does not have a valid object typeというエラーが発生。考えてみれば当然なんですけどNSArrayはObjectしか入れられません。こういう時はラッパークラスのNSNumberでラッパーしてNSArrayにいれてやります。

//selectedListはNSMutableArray
for(NSNumber *row as selectedList)
{
//ここでなにか
}

    このエントリーをはてなブックマークに追加

Viewをnibファイルから読み込んで表示するとき様々なタイミング初期化メソッドが呼ばれます。


#import "ViewBaseViewController.h"

@implementation ViewBaseViewController
@synthesize label;

- (void)loadView {
[super loadView];
NSLog(@"loadView");
}

- (void) viewWillAppear:(BOOL)animated
{
NSLog(@"viewWillAppear");
}

- (void) viewDidAppear:(BOOL)animated
{
NSLog(@"viewDidAppear");
}

- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"viewDidLoad");
}

- (void)dealloc {
[label release];
[super dealloc];
}

@end
実行すると

ViewBase[12262:207] loadView
ViewBase[12262:207] viewDidLoad
ViewBase[12262:207] viewWillAppear
ViewBase[12262:207] viewDidAppear
こんな順番で呼ばれます。気をつけなかればいけないのはloadViewとviewDidLoadはnibが最初に読み込まれる時だけ呼ばれます。Viewを切り替えて使うようなアプリケーションで切り替え時にUIの値を変更したい時はviewWillAppearでやらなければなりません。

それと、もう一点、UIの値を変更するタイミングですが、nibが読み込まれるまで変更はできません。例えばアプリケーションのデリゲートメソッドapplicationDidFinishLaunchingで

- (void)applicationDidFinishLaunching:(UIApplication *)application {
viewController.label.text = @"foo bar";
[window addSubview:viewController.view];
[window makeKeyAndVisible];
}
こんな風にやっても、nibを読み込む前なのでOutletが接続されていません。このタイミングで変更しても反映されません。javascriptで対象HTML要素が読み込まれる前に変更を試みるのとにてる感じです。

    このエントリーをはてなブックマークに追加

iPhoneではおなじみのUITableViewでドリルダウンしていくナビゲーションを作ろうと思います。

ちょっと厄介です。

まず、あの階層構造を構築するのにUINavigationControllerを使います。UINavigationControllerはスタックになっていて、UIViewControllerのサブクラスであればなんでもpushできます。pushするとその表示がControllerにかわる感じです。

最初に表示されるViewはなんなのかというと、UINavigationControllerは中にRootViewControllerとしてViewControllerのサブクラスを持っていて、こいつを最初に表示します。

この辺の設定はInterfaceBuilderでやることになります。InterfaceBuilderでNavigationControllerをMainWindow.xibにドロップして、NavigationController内のRootViewControllerのクラスを自分で作成したクラスに変更してやります。

指定したViewControllerは自動でインスタンス化されるので、テーブルのセルが選択されたときにUINavigationControllerに新しいViewControllerをpushします。


- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger row = [indexPath row];
SecondLevelViewController *nextController = //なにか新しいViewController

[self.navigationController pushViewController:nextController animated:YES];
}
didSelectRowAtIndexPathはUITableViewDelegateののメソッドで、テーブルの行が選択された時に呼ばれます。UINavigationControllerにスタックされたViewControllerからはnavigationControllerでUINavigationControllerを参照できるようです。ここに新しいViewControllerを追加してってやれば、どんどん深い階層のナビゲーションを作れます。

階層を戻っていくのはどうするのかというと、InterfaceBuilderでUINavigationControllerを使った場合は何もしなくても、戻る動作もボタンも実装されます。すごい!

    このエントリーをはてなブックマークに追加

最近、iPhoneアプリ開発の勉強をしてます。ちょこちょこ書くかもしれません。

UIImageのimageNamedというメッセージでちょっとはまったので書いておきます。
UIImageのimageNamedはMainBandleからファイル名で簡単に画像をロードできます。


UIImageView *image = [UIImageView imageNamed: @"image.png"];
このメソッドは読み込んだ画像をパスをキーにしてキャッシュします。なのでreleaseして再度同じ画像を読み込もうとするとクラッシュします。また、アプリ内で何度も使う画像を読むのには向いていますが、サムネイル表示のような、一時的に使う画像を大量に扱うのには向いていません。そのときは

NSString *path= [[NSBundle mainBundle] pathForResource:@"star" ofType:@"png"];
UIImage *image= [[UIImage alloc] initWithContentsOfFile:path];
cell.thumb.image = image;
[image release];
このように生成します。
URLからUIImageを生成するときは一旦NSDataを作ります

NSString *path = @"http://画像のURL";
NSURL *url = [[NSURL alloc] initWithString:path];
NSData *data = [[NSData alloc] initWithContentsOfURL:url];
UIImage *image = [[UIImage alloc] initWithData: data];
cell.thumb.image = image;
[url release];
[data release];
[image release];

    このエントリーをはてなブックマークに追加

phpunitを使ってユニットテストを行いながら開発をしています。データーベース関連のテストで、クエリの数を数えたかったのですが、そのまま使うと、他のテストで発行したクエリまで数えてしまいます。そこで、問題のテストの最初で新しいZend_Db_Profilerのオブジェクトをセットしてやると、新規でログをとり始めるので、うまくできました。


$db = $select->getAdapter();
$old_prof = $db->getProfiler();
$db->setProfiler(new Zend_Db_Profiler(true));

//ここでDBにクエリを発行していろいろ実行

$prof = $db->getProfiler();
$prof->setFilterQueryType(Zend_Db_Profiler::SELECT);
$this->assertTrue(1 == $prof->getTotalNumQueries());
$db->setProfiler($old_prof);
これで、今回のクエリーだけカウントが取れます。ただ、全体のログから、今回のログが除かれてしまいます。戻せそうだなあと思い、コードを追ってみた結果、これを$old_profに戻すのはZend_Db_Profilerでは難しそうです。

//↑の$db->setProfiler($old_prof);の前で
foreach($prof->getQueryProfiles(Zend_Db_Profiler::SELECT) as $query)
{
$id = $old_prof->queryClone($query);
$old_prof->queryEnd($id);
}
$db->setProfiler($old_prof);
これで、一応戻せます。しかし実行時間がおかしなことになります。問題なのはクエリを外から加えるメソッドがqueryCloneしかなく、Zend_Db_Profiler_Queryはcloneの中でかかった時間をクリアしています。で、queryEndで終了させてやれば出るのですが、実行時間がqueryCloneを実行してからqueryEndが実行されるまでの時間になってしまいます。
現状ではZend_Db_Profilerを継承したクラスを作ってクエリリストにそのまま、加えられるようにしないとだめそうです。

    このエントリーをはてなブックマークに追加
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。