忍者ブログ

[PR]

2025年01月31日
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

データ関係のオブジェクト

2009年07月07日
ホームページのプログラミングのコーナーにもそれなりにコンテンツが増えてきました。現在は自作アプリケーションのデータを入れるのに使いそうなオブジェクト、という部分に焦点を絞って簡単な説明を作ってみています。NSStringについての説明がずいぶんと長くなってしまいましたが、いろいろな機能がある分仕方ないのでしょう。

ブログの編集ウインドウで編集するよりは長文の場合でも全体が見渡しやすく楽ですが、スタイルの設定や改行のチェックをしなくて良いのはブログの方が便利ですね。コードをそのまま貼り付けなどという手抜きも出来ましたし(おいおい…)。あとはNSMutableStringとNSNumberくらいは説明しないと駄目だろうな、などと考えています。
PR

現在ホームページの改装工事中です

2009年07月04日
こちらのブログではなくホームページの側の話ですが、現在リニューアル工事の真っ只中です。こちらのブログの内容をちょっとずつまとめたページもこっそりと追加していたりします。まあ基本事項の時点でかなり寄り道しているので、こちらの記事のメインになっているUITableViewやSQLite3の話に到達するのはいつの日になるやら、という感じです。レイアウトの基本構造を決定していざ現在のページを置き換え始めたところでTiny3Dバージョン2.0のReady for saleになりましたよメールが届き、大慌てでストアの写真を入れ替えたりと、なんだがバタバタした状況になっています。

Tiny3D 2.0 配信開始しました

2009年07月04日
かなり審査に時間がかかりましたが、Tiny3Dバージョン2.0が本日よりiTunes Storeで配信開始となりました。iPhone 3.0ソフトウェアアップデートにより各アプリが3.0対応の新版でも出していて混み合っているのか、それとも内容が肥大化しすぎてテストに時間がかかったのか、果たしてどちらなのでしょうか。その結果は現在審査中の新アプリのリリース(またはリジェクト)の期間でわかるかもしれません。

自分のアプリケーションのデータを標準のメールで送る

2009年06月29日
これまでは自分のアプリケーションで作ったデータをiPhoneから外へ出そうとすると、様々な困難がありました。標準のメール機能へファイルを受け渡す事が出来なかったからです。画像については標準の写真アプリにファイルを送る事が出来るため、写真アプリへデータを渡し、写真アプリを開いて画像を表示、さらにアクションからメールへ添付することで一応外へ出す事が出来ましたが、それもかなり回り道をしている状態でした。

私も自分のアプリケーションが持つデータを外へ出すために四苦八苦し、自前でSMTPやFTPのクライアント機能を実装してなんとか出口を作ってきました。ですがこれからはそんな苦労をしなくても簡単にメール添付でのデータ送信ができます。それは3.0ではMessageUIが追加されたからです。実際の利用方法はアップル提供のサンプル「MailComposer」を詳しく見れば分かると思います。簡単に説明すると、まずメール送信のビューへ進みたいビューのコントローラーのヘッダファイルへ

#import <MessageUI/MessageUI.h>

#import <MessageUI/MFMailComposeViewController.h>

を追加し、さらにMFMailComposeViewControllerDelegateに反応させるようにします。あとはメソッドファイル側でMFMailComposeViewController*型の変数を作り、必要なら宛先やCC、BCCの情報をそれぞれNSArrayにして渡します。さらに添付データをNSDataで、本文をNSStringで渡します。最後にこのメール編集用のコントローラーを表示させます。

メールを送信したか等の結果は

- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error


で受け取ります。当たり前ですがMessageUI.frameworkの追加は忘れずに行いましょう。MailComposerのプロジェクトを開いておいて、自分のプロジェクトへドラッグアンドドロップしてしまうのが簡単で良いと思います。

起動時のステータスバーの状態を変更する

2009年06月26日
ステータスバーのタイプ(スタイルと呼ばれます)は標準的なタイプ(UIStatusBarStyleDefault)、黒いタイプ(UIStatusBarStyleBlackOpaque)、黒くて透けるタイプ(UIStatusBarStyleBlackTranslucent)の3つがあり、自分の好みで選べます。また、表示をさせなくする事も出来ます。たとえば代表クラスのapplicationDidFinishLaunchingに、

[application setStatusBarStyle:UIStatusBarStyleBlackOpaque animated:YES];

 
と書いておくと、ステータスバーが黒くなりますし、

[application setStatusBarHidden:YES animated:YES];

 
と書けばステータスバーが上に引っ込みます。プログラムの任意の場所で変えたい場合は、

[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackOpaque animated:YES];

[[UIApplication sharedApplication] setStatusBarHidden:YES animated:YES];

 
と書けば、その場所でステータスバーのスタイルが変わったり、ステータスバーが消えたりします。でもこれらはあくまで起動してからの話です。従って、コードで書く場合では一番早い段階のはずの代表クラスのapplicationDidFinishLaunchingに書いたとしても、起動中のステータスバーは標準値(UIStatusBarStyleDefault)のままで、起動処理が終わったあとでようやく切り替わります。では始めから状態を変えるにはどうするかというと、info.plistに設定値を書きます。

ステータスバーのスタイルは今選択されている行の右にあるプラス部分をクリックして行を増やし、キーにUISatusBarStyleと入力してエンターを押し、値には先ほどの3つのどれかを指定します。ステータスバーを隠した状態で起動させたい場合はキー部分にUIStatusBarHiddenと書いてエンターキーを押せば、値の部分にチェックボックスが表示されるので、そのチェックを外しておけばOKです。

現在の3.0用のSDKで作ったプロジェクトの場合、このように指定しようとキーを記入すると、キーが勝手にStatus bar styleやStatus bar is initially hiddenという名称に変更されます。その場合はスタイルの値をGray style (default)、Transparent black style (alpha of 0.5)、Opaque black styleの中から選びます。

ステータスバーのスタイルで透過を選んだ場合、ステータスバーの背後にDefault.pngの画像が透けて表示されます。スクリーンショットをそのまま使っている場合などは、ステータスバーの部分を白く塗りつぶすなど編集しておきましょう。そのままの状態にしておくと、スクリーンショットのステータスバーが現在のステータスバーの背後に重なって表示されてしまいます。

UITableViewControllerはどこへ行った?

2009年06月22日
iPhone SDK 3.0では新規にファイルを作る場合の種類の選択方法が今までとは少し変更が加わっています。以前は開いたウインドウの左側にあるリストからiPhone OSのCocoa Touch Classを選び、右側に表示される多数のアイコンの中からUITableViewController subclassを選んでいました。しかしiPhone SDK 3.0ではアイコンはObjective-C classとObjective-C test case class と UIViewController subclassの3つしか表示されません。

UIViewControllerのアイコンだけがそのまま残されているため、ぱっと見で今までの選択用アイコンがインストールに失敗して消えてしまったかのように思えます。私はしばらくの間これで大丈夫なのかと不安になりました。でもこれでは別に異常ではなく、正常な状態のようです。ではUITableViewController subclassやUITableViewCell subclassなどはどこに行ってしまったのでしょうか。
つづきはこちら "UITableViewControllerはどこへ行った?"

iPhone OS 3.0 におけるセルの変更点

2009年06月21日
3.0になったことによる、UITableView関連での変更点はUITableViewCellの変更だけのようです。これまではセルそのものがUILabelのようにtextを持っていたのですが、3.0以降ではセルは2種類のラベルを持ちます。textLabelとdetailTextLabelです。従って、3.0専用にアプリケーションを作る場合には、今までとは少しだけセルへのテキストの渡し方が変わります。これまで「セルの変数名.text」だったのが、「セルの変数名.textLabel.text」や「セルの変数名.detailTextLabel.text」になります。また、セルの作成時の宣言がフレームからスタイルに変更されています。スタイルは4種類の中から選びます。文章で書いていても分かりにくいので、スクリーンショットを掲載します。

cell3.PNG左にある画像が4種類のスタイルをそれぞれ適応したセルです。一番上がUITableViewCellStyleDefaultです。textLabelだけ表示される、今までに近い形の表示です。次がUITableViewCellStyleValue1です。タイトルと値を表示しますが、セルの幅を全て使う表示になります。その次がUITableViewCellStyleValue2です。タイトルと値が寄せて表示されます。最後がUITableViewCellStyleSubtitleです。2つのラベルが上下に並んで表示されます。ちなみに画像もこれまでは「セルの変数名.image」でしたが、「セルの変数名.imageView.image」となります。画像はスタイルがUITableViewCellStyleDefaultとUITableViewCellStyleSubtitleの場合だけラベルの左に挿入されます。


以下は上のスクリーンショットを撮影するのに使ったコードです。Navigation-based Applicationを選んでRootViewController.mの該当箇所をこのコードのように書き換えれば同じように表示されるはずです。Xcodeにそのままコピー&ペーストできるようにレイアウトはいじっていません。なお、これだけ少数のセルなので表示は全く問題ないはずですが、一応複数種のセルを使っていることもあるので、以前の記事『数種類のセルを使用してもスクロール速度の低下を極力減らす方法』と同じ書き方にしてあります。

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    return 4;

}

 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {    

// 行ごとに表示を変更します。

switch (indexPath.row) {

case 0: {

UITableViewCell *cellDefault = [tableView dequeueReusableCellWithIdentifier:@"cellDefault"];

if (cellDefault == nil) {

cellDefault = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cellDefault"] autorelease];

}

cellDefault.textLabel.text = @"textLabel";

return cellDefault;

}

break;

case 1: {

UITableViewCell *cellValue1 = [tableView dequeueReusableCellWithIdentifier:@"cellValue1"];

if (cellValue1 == nil) {

cellValue1 = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"cellValue1"] autorelease];

}

cellValue1.textLabel.text = @"textLabel";

cellValue1.detailTextLabel.text = @"detailTextLabel";

return cellValue1;

}

break;

case 2: {

UITableViewCell *cellValue2 = [tableView dequeueReusableCellWithIdentifier:@"cellValue2"];

if (cellValue2 == nil) {

cellValue2 = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:@"cellValue2"] autorelease];

}

cellValue2.textLabel.text = @"textLabel";

cellValue2.detailTextLabel.text = @"detailTextLabel";

return cellValue2;

}

break;

case 3: {

UITableViewCell *cellSubtitle = [tableView dequeueReusableCellWithIdentifier:@"cellSubtitle"];

if (cellSubtitle == nil) {

cellSubtitle = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"cellSubtitle"] autorelease];

}

cellSubtitle.textLabel.text = @"textLabel";

cellSubtitle.detailTextLabel.text = @"detailTextLabel";

return cellSubtitle;

}

break;

}

    UITableViewCell *cellDefault = [tableView dequeueReusableCellWithIdentifier:@"cellDefault"];

    if (cellDefault == nil) {

        cellDefault = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cellDefault"] autorelease];

    }

return cellDefault;

}

 
2010年5月23日補足:
最後の実際に使われない部分はreturn nil;でもセル数との整合性が失われていなければ全く問題ないのですが、例えばtableView:numberOfRoawsInSection:で戻る値を4から5に変更するとここで空のオブジェクトが返り、結果としてアプリケーションが強制終了されてしまいます。そのような場合でも一応セルオブジェクトを返す事によりアプリケーション全体が落ちるのを避けられるようにしているため、このような一見すると面倒な表記になっています。

巨大化したメソッドファイルをカテゴリを使って分離する

2009年06月20日
アプリケーションの処理でついつい代表クラスへ丸投げをしていると、代表クラスがどんどん肥大してゆきます。Tiny3Dは代表クラスのメソッドが8千行を超えていた時期もありました。ここまで肥大化させてしまうとXcodeの動作が不安定になりやすいようで、コード補完が妙な動きをしてレイアウトが崩れ、編集メニューの「取り消す」でも取り消せずさらに崩れるような状態になったりします。そのような場合に有効な解決策が、カテゴリの導入です。

まず、新規で分離するファイルと同じ名前に、何か付け足したメソッドファイルを作ります。ヘッダファイルは作らないようにチェックは外しておきます。@implementationの部分に以下のように括弧でくくってカテゴリ名を付け足します。先ほどのファイル名に付け足すものというのはカテゴリ名にしておくと分かりやすいでしょう。


@implementation
Tiny3DAppDelegate (dxf)


そして、その前の部分に移動するメソッドで必要なインポートや定義を書き加えます。そしてヘッダファイルの最後にある@endのさらに後ろにそのカテゴリに移動させるメソッドを宣言しておきます。書き方はこれまでにヘッダファイルでやっていたメソッドの宣言と同じです。違うのはその宣言部分の前後を

@interface Tiny3DAppDelegate (dxf)


@end


で挟むということだけです。括弧の中は先ほど書いたカテゴリ名と同じにします。あとは元からあったメソッドファイルから、新しく作ったメソッドファイルへとメソッドを移動します。これで巨大になったメソッドファイルを分割することができます。同じようにしてカテゴリを複数作れば、メソッドファイルを複数のファイルに分散させる事も出来ます。メッセージ類は今までと全く同じままで良く、オブジェクトの内外ともに書き換える必要はありません。ちゃんとカテゴリ内のメソッドへもメッセージが届きます。まあ、そのためにヘッダ側でメソッドを宣言しているわけですが。なお、オブジェクト内部の変数はこれまで通りヘッダファイルの元々のインターフェース内で宣言、@synthesizeも元からあるメソッドファイルへと書くようにしましょう。