COMPANY

BLOGS

  • user warning: Unknown column 'u.signature_format' in 'field list' query: SELECT c.cid as cid, c.pid, c.nid, c.subject, c.comment, c.format, c.timestamp, c.name, c.mail, c.homepage, u.uid, u.name AS registered_name, u.signature, u.signature_format, u.picture, u.data, c.thread, c.status FROM comments c INNER JOIN users u ON c.uid = u.uid WHERE c.nid = 16475 AND c.status = 0 ORDER BY c.cid LIMIT 0, 50 in /var/www/www.4d.com/docs/modules/comment/comment.module on line 991.
  • warning: file_get_contents(http://www.telize.com/geoip/54.81.210.99) [function.file-get-contents]: failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found in /var/www/www.4d.com/docs/includes/common.inc(1762) : eval()'d code on line 4.

iPhone Tutorial #01

31.05.2010
by Keisuke Miyako

iPhone OS 3.1(iPhone)およびiPhone OS 3.2(iPad)で実行できるアプリケーションは"JavaScriptとDashCode"あるいは"Objective-CとXCode"いずれかの組み合わせで作成することができます。4DとiPhone/iPadは, SQLやWeb Servicesなどにより相互に対話することができますが, iPhone OSのプログラムは, Appleが提供する標準のツール, つまりDashCodeまたはXCodeだけを使用し, JavaScriptまたはObjective-C言語でコーディングしなければなりません(クロス・コンパイルの禁止)。いずれにしても, この機会にXCodeやObjective-Cを始めようと考えている4Dデベロッパーは多いと思います。

 

 〜今回の目標〜

 

■シミュレータービルド

■デバイス(Developer)ビルド

■デバイス(Ad Hoc Distribution)ビルド

 

 

最新版のXCodeがインストールされたIntel Macが利用でき, iPhone Developer Programに入会していることが前提です。CocoaやObjective-Cに関する情報は,さまざまな書籍やチュートリアルで丁寧に解説されていますので, 必要に応じてそのようなものを参照するようにしてください。

 

developer.apple.com/jp/programs/iphone/

 

■シミュレータービルド

 

XCodeを起動し, 新規プロジェクトを作成します。それぞれのデバイスに最適のテンプレートが用意されています。

 

iPhoneのみ
- Navigation Based Application
- Utility Application

 


iPadのみ
- Split View Based Application


iPhoneまたはiPad
- Tab Bar Application
- View Based Application
- Window Based Application

 

最初はView Based Applicationがシンプルなのでお勧めです。プロジェクト名は何でも構わないのと思いますが, 仮に"Hello World"とした場合, アプリケーションのメイン処理を記述するクラス(Application Delegate)のクラス名およびインタフェースの処理を記述するクラス(View Controller)のクラス名に"Hello_World"というプリフィックスが付けられることを意識するようにしてください。

 

main.m

 

Objective-Cに慣れていない場合, プログラムの実行順序を追ってコードを完成させてゆくと分かり易いと思います。Cの伝統に倣い, main.mファイル(拡張子.mはmixedの略でObjective-Cファイルのこと)のmain関数がプログラムの開始点です。XCodeが出力するコードは次のようになっています。

 

int main(int argc, char *argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}

 

ここで注目したいのは, %3と%4(それぞれnil)です。%3はprincipalClassNameで, nilであれば, UIApplicationになります。特殊なアプリケーションでない限り, ここはnil(UIApplication)で問題ないはずです。%4はdelegateClassNameで, ここに前述したApplication Delegateのクラス名をNSStringの定数(@"文字列")で記述します。つまり, @"Hello_WorldAppDelegate"のような文字列で置き換えます。

 

...AppDelegate.h

 

@class Hello_WorldViewController;

@interface Hello_WorldAppDelegate : NSObject <UIApplicationDelegate>
{
UIWindow *window;
Hello_WorldViewController *viewController;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet Hello_WorldViewController *viewController;

@end

 

@classというのは, 続く識別子がクラス名であることをコンパイラに予告するもので, これによりコンパイラ(そしてデベロッパー)はファイルをすべて解析しなくても, それがクラス名であることを最少限の労力で知ることができます。このファイルの途中で言及されているHello_WorldViewControllerクラスは, この時点では暗示的なクラスですが, 後に別のファイル(Hello_WorldViewController.hおよび.m)でインタフェースとインプリメンテーションが(予告どおり)記述されているので, 問題がないのです。

 

@interfaceから@endの間に記述されているのが, クラスのインタフェースです。最初の行はクラスが継承するスーパークラス(この場合はUIApplicationDelegate)を明らかにしています。続く2行はこのクラスのプロパティのタイプと変数名です。標準的なiPhone/iPadアプリケーションは最低限UIWindowとUIViewController(のサブクラス)があるはずなので, テンプレートもそのようになっています。

 

@propertyは, Objective-C 2.0で拡張された仕様で, 前述のプロパティにアクセスするメソッド(ゲッターとセッター)をコンパイラが自動的に出力するとともに, ドットシンタックス([instance setProperty]の代わりにinstance.property = ...と記述すること)によるアクセスを可能にするものです。

 

...AppDelegate.m

 

@synthesize window;
@synthesize viewController;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[window addSubview: viewController.view];
[window makeKeyAndVisible];

return YES;
}

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

 

@synthesizeは, 言及したプロパティ(ここではwindowとviewController)のゲッターとセッターを作成するようにというコンパイラに対する命令です。windowプロパティの場合, .hファイルの中でread onlyと指定しなかったのでwindowおよびsetWindowというゲッター/セッターペアが作成され, かつretainと指定されているのでsetWindowはretainメソッドをコールするようなコードをコンパイラが自動的に出力します。さらにnonatomicと指定されていることは, ゲッター/セッターペアのコードに別のスレッドからの同時アクセスを防止するインターナルロックを特に実装しないで単純に値を読み書きするようなコードが出力されることを意味しています。

 

developer.apple.com/...ocProperties.html

 

- application:didFinishLaunchingWithOptions:というインスタンスメソッドは, 初期のSDKでは返り値が(void)の...didFinishLaunchingとなっていたので, そのように紹介されている資料もあるようです。アプリケーションが起動した後のスタートアップメソッドに相当します。

 

window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]];
viewController = [[Hello_WorldViewController alloc]init];

[window addSubview:viewController.view];
[window makeKeyAndVisible];

 

標準のiPhoneアプリケーションナビゲーションバーを追加することもできます。

 

window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]];
viewController = [[Hello_WorldViewController alloc]init];
navigationController = [[UINavigationController alloc]initWithRootViewController:viewController];

[window addSubview:navigationController.view];
[window makeKeyAndVisible];

 

その場合, インタフェース側にもナビゲーションバーをプロパティとして追加し, @property, @synthesize, - deallocメソッドにもナビゲーションバーを追加し, クラス定義, ゲッター/セッター出力, インスタンス解放のコードを用意することになります。

 

...ViewController.h

 

@interface Hello_WorldViewController : UIViewController
{
UIImageView *contentView;
}

@end

 

もっともシンプルな形のインターフェースコードです。

 

...ViewController.m

 

コメントアウトされた格好で, さまざまなデレゲートメソッド(いわゆるイベントのようなもの)のコードが用意されています。今回, 特に注目したいのは下記のふたつです。

 

- shouldAutorotateToInterfaceOrientation:interfaceOrientation

 

デバイスの向きに合わせて画面を回転させるかどうかの設定です。return YES;とすることにより, 回転をOSが自動的に処理してくれるようになります。

 

- loadView

 

このコントローラーが表示されたときに実行される(On Loadイベントに相当)コードです。下記のようなコードを記述することにより, 最低限の処理をさせることができます。

 

- (void)loadView
{
contentView = [[UIImageView alloc]initWithFrame:[[UIScreen mainScreen]applicationFrame]];

[contentView setImage:[UIImage imageNamed:@"helloworld.png"]];

self.view = contentView;
[contentView release];

contentView.autoresizesSubviews = YES;
contentView.autoresizingMask = (UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight);
}

 

imageNamed:メソッドにはファイル名を渡していますが, iPhone/iPadのバンドルパッケージは一般的なMac OS Xアプリケーションとは違い, 階層がひとつしかない(Content, Resources, Mac OSなどがない)ので, プロジェクトに含まれたファイルは基本的にファイルだけで参照することができます。つまり, "helloworld.png"ファイルをXCodeの「グループとファイル」にドロップするだけで, アプリケーションのリソースとしてその画像が利用できるようになります。

 

続くプロパティアクセスは, Objective-C 2.0ならではのコーディングであり, 非常に便利なのですが, 注意も必要な部分です。self.view = contentViewという代入文のような命令は, 実際にはクラスプロパティのセッターメソッドをコールしているのであり, この場合, viewプロパティがretainと定義されていることから, 実際には渡されたオブジェクトのretainカウントがインクリメントされています。そのようなわけで, 直後の行でreleaseしても大丈夫なのであり, むしろreleaseしなければメモリーリークの原因になるので注意が必要です。iPhone OSは構造的にガーベージコレクションが不可能とされており, オブジェクトのretainとreleaseは完全にデベロッパーの責任であると言われています。

 

次の2行は前述のデバイス回転に対してこのビューがどのように振る舞うべきかを指定するものです。

 

ビルド前にもうひとつできることがあるとすれば"icon.png"という名前の57x57ピクセル画像をプロジェクトに含めることが挙げられます。このファイルは, SpringBoard(iPhone OSのFinderのこと)に表示されるアイコンであり, 自動的に角が丸くてツヤのあるイメージに変換されるので, ツヤがなく角のとがった画像を用意するようにします。

 

この時点でコードの骨組みが作成されますので, 起動/終了だけであれば, すぐにでもビルドして実行することができます。

 

XCode左上の構成ポップアップがSimulator - 3.1.3 (iPhone) またはSimulator - 3.2 (iPad) に設定されていることを確認し, ビルド&実行します。

 

■デバイス(Developer)ビルド

 

シミュレーターは手軽で便利なものですが, できればすぐにでもデバイスでデバッグがしたいものです。デバイスでアプリケーションをデバッグするためには, iPhone Developerに加入し, 「証明書」と「Provision」を発行する必要があります。おおまかな流れは下記のとおりです。

 

■キーチェーンアクセスで証明書を要求

■iPhone Provisioning Portalで証明書を発行

■ キーチェーンアクセスに証明書をインストール

■iPhone Provisioning PortalでProvisionを作成

■XCodeにProvisionをインストール

 

■キーチェーンアクセスで証明書を要求

アプリケーション/ユーティリティにあるキーチェーンアクセスを起動し, 証明書アシスタントメニューより「認証局に証明書を要求」します。画面上, CAのメールアドレスは必須となっていますが, 入力しなくも大丈夫です。要求(CSRファイル)はディスクに保存します。後述するように, 証明書はDeveloper ProvisionとDistribution Provisionでそれぞれ必要なので, 見分けるためにファイル名を区別すると良いかもしれません。(デフォルトはCertificateSigningRequest.certSigningRequest)

 

■iPhone Provisioning Portalで証明書を発行

http://developer.apple.com/iphone/index.actionにアクセスし, Apple IDでログインして, iPhone Dev Centerに移動します。画面に右上にあるリンクよりiPhone Provisioning Portalに進みます。画面の指示に従い, キーチェーンアクセスで出力したファイルをアップロードしてください。直後, 証明書の発行が"pending"と表示されますが, 別のタブをクリックして戻るなど, 画面を切り替えれば, すぐにでも"download"に表示が代わり, 証明書を入手することができます。

 

■ キーチェーンアクセスに証明書をインストール

iPhone Dev Centerの説明では, ダウンロードした証明書(CERファイル)をダブルクリック(あるいはキーチェーンアクセスにドロップ)すれば良いとなっていますが, うまくいかない場合(システムルートは変更できませんエラー), ファイルメニューから読み込めば大丈夫のはずです。

 

■iPhone Provisioning PortalでProvisionを作成

Provisionは, ワイルドカードの署名を作成することが勧められています。つまり"com.4D.miyako.*"のような識別子です。そのようにすれば, 以後, iPhone/iPadアプリケーションのバンドル識別子を"com.4D.miyako.HelloWorld"のように展開し, 同一のProvisionが一貫して利用できるからです。

 

■XCodeにProvisionをインストール

iPhone Dev CenterからダウンロードしたProvision ファイル (拡張子mobileprovision)をXCodeにドロップするだけでインストールすることができます。Developer Provision野詳細はXCodeのオーガナイザで確認することができます。

 

デバイスを使用してアプリケーションをデバッグするには, XCode左上の構成ポップアップメニューでDevice - 3.1.3などを選択してください。このときプロジェクトのInfo.plistでBundle identifierがProvisionのアプリケーション識別子と合致していなければいけません。

 

■デバイス(Ad Hoc Distribution)ビルド

 

作成したiPhone/iPadアプリケーションは, 100台までの登録されたiPod Touch/iPhone/iPadなどにインストールすることができます。Apple Storeを経由しないそのような配付はAd Hoc Distributionと呼ばれています。Ad Hoc Distributionには, 専用のDistribution Provisionが必要です。つまり, 前述のDeveloper Provisionと同じ要領で証明書リクエスト, 証明書, Provisionを作成しなければなりません。

 

Ad Hoc Distributionをする場合, プロジェクトのビルドもいくらか余分の手順が求められています。まず, Distribution ProvisionをXCodeのインストールした後, XCodeのファイルメニューより新規ファイル→Code Signing→Entitlementsを選択し, "dist.plist"などと名前を付けてEntitlementsを保存してください。作成したEntitlementsをXCodeで編集し, get-task-allowのチェックを解除します。

 

ここからが少し複雑です。はじめにグループ&ファイル最上位のプロジェクトアイコンをダブルクリックするなどして, プロジェクトの情報を開きます。ここで「構成」タブへ移動し, "Release"構成を複製して"Distribution"と命名します(つまりReleaseをベースに新しい構成を作成します)。ここでプロジェクトの情報を閉じます。

 

メインの構成ポップアップメニューより作成したばかりのDistributionを選択します。

 

次にグループ&ファイル中段のターゲットを展開, ダブルクリックするなどして, ターゲットの情報を開きます。ここでは「ビルド」タブに移動し, 構成ポップアップメニューよりDistributionを選択します。同じ画面で, Code Signing Entitlementsに"dist.plist"(あるいは作成したEntitlementsのファイル名)を入力します。すぐ下のコード署名IDでAd Hoc Provisionと証明書の組み合わせを選択して完了です。つまりプロジェクトとターゲットのそれぞれでDistribution 構成を選択するのが大事です。

 

この設定でビルドを実行すると, Ad Hoc Provisionが組み込まれたパッケージが作成されます。これはそのままZIP圧縮して配付することができ, iTunesにそのままドロップすることができます。