タグ「iPhone」が付けられているもの

iOSのInterfaceBuilderを使ってみる

先日作成したiPhone3GのOpenGLアプリに、簡単なUIを付け加えたので、行った手順を記録する。

●Setupボタンを追加してみる

  1. MainWindow.xibを開く(*1)
    → InterfaceBuilderの画面が開く。
  2. Toolbarを貼り付ける

    → Bar Button Itemが1つ勝手に付けられる
  3. "Item"を何かに変える
    "Item"を選択し、Attributeの画面で、IdentifierをCustomから何かに変えると、いくつかの既定のアイコンや文字列が選べる。
    残念ながら「設定」っぽいアイコンが無いので、今回は"Edit"にしてみた。

    Titleを"Setup"に変えることもできたが、省略した。
  4. コールバックメソッドを宣言する
    GLViewController.hに
    - (IBAction)setup:(UIBarButtonItem *)sender;
    という宣言を追加する。(*2)(*3)
    UIBarButtonItemというクラス名は、Identity Inspectorで調べることができる。
  5. UIとメソッドを関連付ける
    MainWindow.xibを開き、"View Controller"(GLViewControllerクラスに対応している)を選択し、Connections inspectorのsetupの右の○印(outletと呼ばれる)をUIエディター上の"Edit"までドラッグ

    または、UIエディター上で"Edit"を選択し、Ctrlを押しながら"View Controller"までドラッグ
    ドラッグしたら、○印の中に黒丸が付くことを確認する。
  6. コールバックメソッドを定義(実装)する
    とりあえず、ボタンが押されたらログ出力するよう、GLViewController.mに
    - (IBAction)setup:(UIBarButtonItem *)sender
    {
        NSLog(@"GLViewController.setup called.");
    }
    を追加する。

以上でシミュレーター上で実行し、ボタンが押されたらログが出ることを確認した。

(*1)今回使用したテンプレートに、ViewControllerに対応するXIBファイル(GLViewController.xib)が無いので、今回はMainWindowにボタンを追加した。

(*2)GLViewControllerクラスに置くのが最善かは不明。 MainWindow.xibのOwnerはUIApplicationクラスなので、XxxAppDelegateクラスに置くことも考えられるが、IBのコールバックメソッドはUIViewControllerクラスに置かれることが多いので、GLViewControllerクラスを選んだ。

(*3)NIB File(XIB File)のAction Methodは全て

- (IBAction)setup:(id)sender;
この形らしい。(詳しくはHelpで"IB action methods"を検索、idはObjective-Cの基底クラス)

●スピード調整バーを追加してみる

上記の手順で作ったEditボタンの右側が淋しいので、Toolbarの余白に

こういうのを入れてみる。

  1. MainWindow.xibを開き、LabelとSliderとText Fieldを追加

    LabelはToolbarのItemにはならず、Labelを無視して左詰めされてしまうので、Flexible Space Bar Button Itemを置いてスペースを確保する。
    Labelの文字列は"Interval"にし、Sliderの値の範囲は1〜100(フレーム間隔が1ms〜100msの意味)に変更する。
  2. GLViewController.hにメンバー変数とコールバックメソッドの宣言追加
    メンバー変数は、プログラムで変化させる部品について作成する。
    @interface GLViewController : UIViewController <GLViewDelegate>
    {
        IBOutlet UITextField* textField;
        IBOutlet UISlider *slider;
    }
    - (IBAction)slided:(UISlider *)sender;
    - (IBAction)setup:(UIBarButtonItem *)sender;
    
  3. UIとメンバー変数、メソッドを関連付ける
    MainWindow.xibを開き、"View Controller"を選択し、textField, sliderのoutletから部品へドラッグして接続
    slidedのoutletをSliderにドラッグし、Value Changedを選択して接続
  4. GLViewController.mにメソッド定義追加
    - (IBAction)slided:(UISlider *)sender
    {
        /* スライダーに連動してテキストボックスの文字列更新する */
        NSString *text = [[NSString alloc]initWithFormat:@"%d ms", (int)sender.value];
        [textField setText:text];
        [text release];
        /* アニメーション速度を変える */
       [(GLView *)self.view setAnimationInterval:sender.value/1000];
    }
    
    /* 起動時にスライダーの位置を初期値に設定する */
    -(void)viewDidLoad
    {
        [super viewDidLoad];
    
        float animationIntervalInMsec = [(GLView *)self.view animationInterval] * 1000;
        [slider setValue:animationIntervalInMsec];
        [self slided:slider]; //テキストボックス初期化のため、slidedメソッドを呼び出し
    }
    

以上で、スライドバーでアニメーションのスピード調整ができることを、シミュレーターで確認した。

●別画面でSetup画面を追加してみる

3Dオブジェクトの複数のバラメーターを操作するための画面を作成してみる。

  1. SetupViewControllerクラスを追加
    XcodeのメニューバーからFile → New → File
    テンプレート選択画面では、iOSの"Objective-C class"を選択
    Option選択画面では、"With XIB for user interface"にチェック
  2. SetupViewController.xibを開いて、UI部品一式を追加
  3. SetupViewController.hにメンバー変数とメソッド宣言追加
    @interface SetupViewController : UIViewController
    {
        IBOutlet UISlider* bodyGranularitySlider;
        IBOutlet UILabel* bodyGranularityLabel;
        IBOutlet UISwitch* textureSwitch;
        IBOutlet UISlider* flipperGranularitySlider;
        IBOutlet UILabel* flipperGranularityLabel;
    }
    - (IBAction)bodyGranularitySlide:(UISlider *)sender;
    - (IBAction)textureSwitched:(UISwitch *)sender;
    - (IBAction)flipperGranularitySlide:(UISlider *)sender;
    
    - (IBAction)backToMain:(UIBarButtonItem *)sender;
    @end
    
  4. UIとメンバー変数、メソッドを関連付ける
  5. 3Dオブジェクトのバラメーター変更の為のメソッド追加
    P2Object.hに以下を追加
    + (void)reinitialize;
    
    /* クラス変数へのアクセサー */
    + (bool) useTexture;
    + (void) useTexture :(bool)value;
    + (int) bodyGranularity;
    + (void) bodyGranularity :(int)value;
    + (int) flipperGranularity;
    + (void) flipperGranularity :(int)value;
    
    P2Object.mに以下を追加
    /* クラス変数 */
    static bool useTexture = true;
    static bool drawingShadow = false;
    static int bodyGranularity = 18;
    static int flipperGranularity = 10;
    
    +(void)reinitialize
    {
        /* パラメーターの変化をオブジェクトに反映させる */
        (コードは省略)
    }
    
    + (bool) useTexture
    {
        return useTexture;
    }
    + (void) useTexture :(bool)value
    {
        useTexture = value;
    }
    + (int) bodyGranularity
    {
        return bodyGranularity;
    }
    + (void) bodyGranularity :(int)value
    {
        bodyGranularity = value;
    }
    + (int) flipperGranularity
    {
        return flipperGranularity;
    }
    + (void) flipperGranularity :(int)value
    {
        flipperGranularity = value;
    }
    
    Objective-Cには、クラスメソッドは存在するが、クラス変数という概念が存在しないので、Cのコードをそのまま使う等の理由でインスタンスを生成せずにクラスメソッドで全てを実装している場合は、このように、状態を保存する変数を.mファイル内で静的変数にして、クラスメソッドとしてアクセサーを用意するしか無さそうである。
  6. SetupViewのコールバックメソッドの定義追加
    SetupViewController.mに以下を追加する。
    #import "P2Object.h"
    
    - (IBAction)bodyGranularitySlide:(UISlider *)sender
    {
        /* スライドバーの数値を右側のラベルに反映させる */
        NSString *text = [[NSString alloc]initWithFormat:@"%d", (int)sender.value];
        [bodyGranularityLabel setText:text];
        [text release];
        /* スライドバーの数値をオブジェクトのパラメーターに反映させる */
        [P2Object bodyGranularity:sender.value];
    }
    - (IBAction)textureSwitched:(UISwitch *)sender;
    {
        /* ユーザー操作結果をオブジェクトのパラメーターに反映させる */
        [P2Object useTexture:sender.on];
    }
    - (IBAction)flipperGranularitySlide:(UISlider *)sender
    {
        /* スライドバーの数値を右側のラベルに反映させる */
        NSString *text = [[NSString alloc]initWithFormat:@"%d", (int)sender.value];
        [flipperGranularityLabel setText:text];
        [text release];
        /* スライドバーの数値をオブジェクトのパラメーターに反映させる */
        [P2Object flipperGranularity:sender.value];
    }
    
    SetupViewController.mのviewDidLoadメソッドに、以下の、スライドバーやスイッチの値をオブジェクトのパラメーターに初期化するコードを追加する。
        [bodyGranularitySlider setValue:[P2Object bodyGranularity]];
        [flipperGranularitySlider setValue:[P2Object flipperGranularity]];
        [textureSwitch setOn:[P2Object useTexture]];
        /* スライドバーの右のラベルを更新する */
        [self bodyGranularitySlide:bodyGranularitySlider];
        [self flipperGranularitySlide:flipperGranularitySlider];
    
  7. 画面遷移処理追加
    MainWindowの"Edit"ボタンが押されたらSetupViewが開くよう、GLViewController.mのsetupメソッドを以下のように変える。
    #import "SetupViewController.h"
    
    - (IBAction)setup:(UIBarButtonItem *)sender
    {
        SetupViewController *setupView = [[SetupViewController alloc] initWithNibName:@"SetupViewController" bundle:nil];
        [(GLView *)self.view stopAnimation];
        [self presentModalViewController:setupView animated:YES];
        [setupView release];
    }
    
    presentViewControllerでなくpresentModalViewControllerを使っているのは、筆者の端末がiPhone3Gである都合で、iOS5以降でないからである。
    SetupViewの"Done"ボタンが押されたらMainWindowに戻るよう、"Done"ボタンのコールバックメソッドを次のようにする。
    - (IBAction)backToMain:(id)sender;
    {
        [self dismissModalViewControllerAnimated:YES];
        [P2Object reinitialize];
    }
    
    "Edit"ボタン押下時にGLViewController.setupでアニメーションを停止しているので、SetupViewが閉じたらアニメーションを再開するコードを追加する。幸い、MainWindowに戻ったらGLViewController.viewWillAppearが呼ばれるので、そこに追加するのが良さそうである。
    -(void)viewWillAppear:(BOOL)animated
    {
        [super viewWillAppear:animated];
        [(GLView *)self.view startAnimation];
    }
    

●結果

・プロジェクトファイル一式
UsingTheTemplateAndIB.tar.gz

・追加したSetup画面の操作でオブジェクトが変化する様子
Use textureをONにすると→ 腹の白の輪郭がきれい

Use textureをOFFにすると→ Granularity(ポリゴンの細かさ)が50でも汚い

●参考文献

iPhone SDK: Interface Builder Basic Training
筆者は、このページの通りにやってみるだけで、InterfaceBuilderの使い方がほとんどわからない状態から、色々なUI部品を使うことができるようになった。とても良いチュートリアルであった。
XcodeのHelp
リファレンスだけあって、ある程度の知識が無いと理解できない情報が出てくる場合が多いが、何を検索しても何か見つかるし、何よりもサンプルコードが充実しているので、すごく助かる。

今更iPhoneでOpenGLES1.1を動かしてみる

iPhoneでもOpenGLを動かしてみたいと思って、知人から入手したiPhone3Gであるが、3Gというのが曲者だった。

iPhone3Gは、OpenGLアプリを作成するのにいくつかの制約がある。
・OpenGLES2.0が使えない
 OpenGLES1.1しか使えない。
・GLKitが使えない
 GLKitはiOS5以降に含まれているが、iPhone3GはiOS4.2.1までしかバージョンアップできない為。
・ステンシルバッファが使えない

それに対し、iPhone3Gの1つ次の3GSは、OpenGLES2.0が動く。これは、3GS以降のGPUは全てPowerVRのSGXシリーズであるのに対し、3GはPowerVRの"MBX Lite 3D"であることが関係しているようだ。
また、3GSにはiOS5がインストールできるので、そうすればGLKitが使える。
そして、3GSはステンシルバッファが使える。

iPhone3GはARMv6アーキテクチャーである為、Xcode 4.4.1を使用しているが、これに含まれる、iOS Applicationの"OpenGL Game"というテンプレートは、付属のiPhoneシミュレーターでは動いたので、簡単にiPhone3GでOpenGLを始められそうと思ったが、このテンプレートはGLKitを使用しているため、iPhone3Gでは動かなかった。
しかも、このテンプレートはOpenGLES2.0にも対応しているため、冗長である。

その為、GLKitに依存していないOpenGLES1.1用のテンプレートをインターネット上で探した。その結果、以下を発見した。
(1) Xcode 3.xのOpenGL ES Application テンプレート
 OpenGLES2.0も使うようになっているので、シミュレーターでは表示されるがiPhone3Gの実機では表示されないオブジェクト(物体)がある。
 但し、depth bufferは用意されていないらしい。
 また、Xcode 4では開けない。
(2) OpenGL ES 道場(1) - こじ研(携帯メディア) のGLBaseプロジェクト
 Xcode 3.xのテンプレートをベースに、depth bufferが追加されており、多少OpenGLES1.1向けに整理されている。但し、多少GLES2.0用の残骸が残っている。
(3) jlamarche/iOS-OpenGLES-Stuff · GitHub紹介記事)のSimple OpenGL ES 1.1 example
 OpenGLES1.1のサンプルプロジェクト。下記(4)のテンプレートを使用したプロジェクトと類似している。但し、Xcode 4.4.1で確認する限り、そのままではシミュレーターでも動かない。
(4) jlamarche/iOS-OpenGLES-Stuff · GitHub紹介記事)のOpenGL ES 1.1 Project Template
 OpenGLES1.1に特化したテンプレート。Quaternionを扱うためのマクロや、gluLookAt()や、アセンブラで書かれた行列積のマクロが用意されており、専門的な香りがする。
 但し、Xcode 3用のテンプレートであり、Xcode 4以降では開けない。

これらの内、(1)は使用するメリットがほとんど無いので、(2)-(4)について、実際にiPhone3Gで動作するまでに行ったことを記録する。

■(2)-(4)共通の、iPhone3Gのための手順
・"TARGETS"の"Build Settings"の"Architectures"を、"Standard (armv7)"から"armv6"に書き換える
・(推奨)同じく"Build Settings"の"LLVM GCC 4.2 - Code Generation"の所の"Optimization Level"を、"None [-O0]"以外にする
("None [-O0]"にしていると、整数型の割り算や剰余が、libgccの___divsi3や___modsi3を使うコードになることがあり、実機で"Symbol not found: ___divsi3"等のエラーになってハングアップする)

■(2) GLBaseプロジェクトの使用手順
特に何もいじらなくても、そのまま動く。
GLBaseViewController.mのdrawFrameを書き換えれば、OpenGLのコードで好きな描画をさせることができる。

なお、ディレクトリーツリーのルートの"GLBase"をrenameすれば、ディレクトリー内の"GLBase"を含むファイル名を一斉にrenameできる。

■(3) Simple OpenGL ES 1.1 exampleの使用手順
・"git clone https://github.com/jlamarche/iOS-OpenGLES-Stuff.git"等として取得
・(推奨)Build Settingsの画面で"Validate Settings"を実行し、修正を許可
・TARGETSのBuild SettingsのBuild OptionsのCompiler for C/C++/Objective-Cを"LLVM GCC 4.2"に変更(Default Compilerだと実機用のコンパイルがエラーになる)
・そのままではPart6ProjectAppDelegate.applicationDidFinishLaunchingが呼ばれないため、以下のパッチを適用、または同様に変更

--- Original/iOS-OpenGLES-Stuff/Simple OpenGL ES 1.1 example/Classes/Part6ProjectAppDelegate.m
+++ tmp/Simple OpenGL ES 1.1 example/Classes/Part6ProjectAppDelegate.m
@@ -23,6 +23,9 @@
GLViewController *theController = [[GLViewController alloc] init];
self.controller = theController;
[theController release];
+
+ self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
+ self.window.rootViewController = self.controller;

GLView *glView = [[GLView alloc] initWithFrame:rect];
[window addSubview:glView];
--- Original/iOS-OpenGLES-Stuff/Simple OpenGL ES 1.1 example/main.m
+++ tmp/Simple OpenGL ES 1.1 example/main.m
@@ -8,11 +8,12 @@


#import
+#import "Part6ProjectAppDelegate.h"

int main(int argc, char *argv[])
{
NSAutoreleasePool *pool = [NSAutoreleasePool new];
- UIApplicationMain(argc, argv, nil, nil);
+ UIApplicationMain(argc, argv, nil, NSStringFromClass([Part6ProjectAppDelegate class]));
[pool release];
return 0;
}
これで、カラフルな12面体が回転する。
GLViewController.mののdrawFrameを書き換えれば、OpenGLのコードで好きな描画をさせることができる。

■(4) OpenGL ES 1.1 Project Templateの使用手順
これは残念ながらXcode3用のテンプレートであり、Xcode4では使えない。Xcode3とXcode4のテンプレートは互換性が無い上、Xcode4用に書き換えるのも困難なのである。
参考URL:XCode4のプロジェクトテンプレートが作れない! - とっくりばー
Xcode3でこのテンプレートを使ってプロジェクトを作成するのが1つの方法だが、ファイル名や一部文字列を置換するだけなので、そういうスクリプトを作っても良いし、上記URLに載せられているRubyスクリプトでもプロジェクトファイルのコピー&置換ができる。

1. 上記URLのReplacer.rbを使う等により、テンプレートからプロジェクトを作成
2. なぜかGLView.mの場所が間違っているので、Classes/に移動する
3. (推奨)Build Settingsの画面で"Validate Settings"を実行し、修正を許可
4. (推奨)TARGETSのBuild SettingsのBuild OptionsのCompiler for C/C++/Objective-Cを"LLVM GCC 4.2"に変更(Default CompilerだとOpenGLCommon.hのアセンブラを用いたマクロがコンパイルエラーになる)

これで、GLViewController.mののdrawFrameに何かを書けば、OpenGLのコードで好きな描画をさせることができる。
何も書かないと画面が真っ暗になるので、試しに何か表示するなら、drawFrameをiOS-OpenGLES-Stuff/Simple OpenGL ES 1.1 example/Classes/GLViewController.mのものに置き換えてみても良いし、画面が暗い青になるだけで良ければ、1行目の"glColor4f"を"glClearColor"に書き換えても良い。

今更iPhone3Gで自作アプリを動かしてみる

昨年9月に、とある方から、とあるお祝いの品として、使わなくなったiPhone3Gを譲り受けた。
最初から電話として使うつもりは全く無く、iPhoneという物を触ってみたいと思ったのと、丁度、Androidの実機で自作アプリを動かしていた頃で、iPhoneでも自作アプリを動かしてみたいと思ってお願いしたものだ。

入手後すぐ、意気揚々と「すべてのコンテンツと設定を消去」してiOSを最新の4.2.1にバージョンアップすると、ロック画面で「アクティベーションが必要です」か何かのメッセージが出て、何もできなくなってしまった。
数日後にアクティベーション専用SIMというものを手に入れて、起動はできたが、Safariを使ってても全体的に動作が遅いし、App Storeで色々なアプリをインストールしようとしても、「このアプリケーションはこのiPhoneとは互換性がありません」とか「このアプリケーションにはiOS X.Xが必要です」とかと表示されてほとんど失敗し、1週間もするとiPhoneに触るのが億劫になり、同時にiPhone3Gは古すぎて自作アプリを開発する上で条件が悪いことも知って億劫になり、その後はiPodの代わりとして使うだけになっていた。

iPhone3Gとその次機種であるiPhone3GS以降とでは、アプリ開発をする上で大きく異なる点がいくつかある。
・iPhone3Gは、インストールできるiOSのバージョンが4.2.1まで
 それに対してiPhone3GSならiOS 6もインストールできる
・3GはOpenGLES 1.1のみ、3GSなら2.0も使用可能
・3GはARMv6アーキテクチャー、3GSはARMv7アーキテクチャー
従って、折角ならiPhone3GS以降でアプリ開発を始めてみたかったのである。

その後、新しいiPhoneを買うかどうかを迷っていたのだが、年が明けて孔子の論語に記載される所の不惑となる年齢に達したことにより、やっぱり今使っているガラケーに何の不満も無い自分にはこれが使える限り金のかかるスマートフォンは不要、と惑わなくなり、当分iPhoneを買うことは無いと確定したので、もらい物のiPhone3Gで自作アプリを動かすことにした。

●開発環境入手
iPhoneの開発環境はXcodeであるが、3GはARMv6アーキテクチャーなので、Xcodeのバージョンに制約がある。Xcode 4.5でARMv6がサポートされなくなったので、Xcode 4.4.1がARMv6用の最新である(*1)

古いバージョンのXcodeは、https://developer.apple.com/xcode/downloads/の"Additional Tools"の所の"View downloads"というリンクの先のリストからダウンロードできる(Apple IDが必要)。

●iPhone3G用の"Hello, world!"アプリの作成
Xcode 4.4.1にはiPhoneシミュレーターも同梱されているので、シミュレーターで動作するiPhoneアプリならすぐに着手できる。

  1. XcodeのメニューバーからFile→New→Projectとする。
  2. "Choose a template"の画面で、iOS Applicationの"Single View Application"を選ぶ。

    ※Xcode 4.4.1のiOS Applicationのtemplateの内、iOS 4.2.1でも動くのは、"Single View Application"と"Tabbed Application"の2つだけのようである。"OpenGL Game"はiOS 4.2.1にGLKitが無いので動作せず、それ以外はiOS 4.2でStoryboardがサポートされていないのでbuildできない。
  3. "Choose options"の画面では、"Use Storyboards"のチェックは外す。
  4. プロジェクトが作成されたら、左上のソースコードツリーの"ViewController.xib"を開く。
  5. InterfaceBuilder(GUI編集画面)が開くので、"Label"とか"Round Rect Button"とかがある所から"Label"をドラッグし、iPhoneの画面の適当な所にドロップする。
  6. ドロップした"Label"をダブルクリックし、"Hello, world!"に変える。
  7. "Run"を押す
→ シミュレーターが開き、"Hello world!"が表示されるはず。

※4.〜6.について、InterfaceBuilderを使うのでなく、真面目に何らかのソースコードを書く場合は、以下の2つの参考記事のそれぞれの4ページ目辺りを参照されたい。
参考記事:
iOS SDKで始めるObjective-C入門(2):iOSアプリ開発初心者に捧ぐ開発環境Xcodeの概要とインストール - @IT
SDKで始めるiPad/iPhoneアプリ開発の勘所(1):いまさら聞けないiPhone/iPadアプリの作り方の基礎 - @IT

●実機へのインストールについて
さて、これが問題である。

正しくは、"Apple Developer"に登録(無料)した上、"iPhone Developer Program"に登録(有料:$99/year)する必要があり、その上で長大な手順が続く。
参考:ここが大変だよiPhone開発(4):ここが大変だよiPhone実機テスト+iPhone OS 3.0の新機能 - @IT

無料で実機に自作アプリをインストールするには、いわゆるJailBreakを行う以外に、手段が全く無いようである。

今回、特にアプリを配布するつもりが無く、試しに簡単なプログラムを動かしてみたい程度で、しかも時代遅れの機種に、1万円を払うのは厳しい。
このiPhoneは、特に使っておらず、筆者にとっては自作アプリを動かせなければ無用である。JailBreakすることによって再起不能になっても問題無い。
ただ、iPhoneのJailbreakingは法に触れるかどうかがグレーであり、それ故に実施するかどうか悩んだのだが、日本における判例が無いことと、著作権法第20条の2に、プログラムを動かす為のプログラムの改変は同一性保持権の侵害に当たらないとある(*2)ことと、Appleが異議を申し立てていた、アメリカの著作権局が発行したDMCAのJailbreakingに関する見直し条項が、その後の2012年10月22日の改正でも、合法的に入手したプログラムを動作させる為の「携帯無線電話」のプログラムの改変は禁止されない、と維持された(*3)ことから、自作アプリをiPhoneで動作させる目的に限ってのJailbreakingは、2015年10月28日までは違法性を問われる確率が極めて低いと判断し、実施に踏み切った。

以下は、JailBreakingが済んでいることと、iPhoneにsshがインストールされている前提の手順である。
  1. Xcodeの左側のツリー表示の一番上のプロジェクトのアイコンを選び、プロジェクト設定の画面にする。
  2. "PROJECT"と"TARGETS"がある列の、"TARGETS"の所のアイコンを選ぶ。
  3. "Build Settings"の"Architectures"を、"Standard (armv7)"から"armv6"に書き換える(*5)
    編集可能な列が2列あるが、右側の列を操作すると左側の列も連動するので、右側の列を操作すると良い。
  4. 同じく"Build Settings"の"Code Signing"の所を全て"Don't Code Sign"にする。
  5. 下の方にある"Validate Settings"を押して、修正させる。
  6. ツールバーにある"iPhone 5.1 Simulator"を"iOS Device"に変える。
  7. メニューバーから"Product"→"Build"する。(*7)
  8. ツリー表示のProductsの下のXXX.appを右クリックし、"Show in Finder"を選ぶ
  9. ターミナルを開き、
    codesign -fs "[適当な証明書の名前]" [パス]
    とする。[パス]の所は、8.で開いたFinderからdrag&dropする。
  10. iPhoneに転送する。
    1つの方法としては、ターミナルから
    scp -r [パス] root@[iPhoneのIPアドレス]:/Applications/
    とする(*4)
  11. iPhoneを"Respring"する。
    1つの方法としては、sshでiPhoneにログインし、
    killall -HUP SpringBoard
    とする。

●トラブルシューティング
正規の手順だと、iPhoneをPCにUSB接続していると、実機のアプリをデバッガで実行できるのだが、上記の手順だとそれができないので、クラッシュログとデバッグコンソールに頼ることになる(*6)

シミュレーター上では動作しても、実機ではハングアップすることは頻繁にある(*4)
アプリ起動するとハングアップして勝手に閉じてしまう場合、クラッシュログが残っているかどうかを確認する。

  1. iPhone3GをPCにUSB接続する。
  2. "Window"→"Organizer"を開く。
  3. "iPhone3G"の"Device Logs"を開く。
または、MacのiTunesでiPhoneを同期すると、~/Library/Logs/CrashReporter/の中にコピーされるようだが、筆者の経験上、同期してもなかなかコピーされないことがあったので、お勧めしない。

コードが思い通りに動かない場合は、printfデバッグを行う。
  1. コードに、
    NSLog(@"[フォーマット文字列]"[, 引数1, 引数2, ...]);
    を加える。[フォーマット文字列]には、"%d"など、Cのprintfと同じ書式が使えるようである。
  2. "Window"→"Organizer"を開く。
  3. "iPhone3G"の"Console"を開く。
  4. iPhoneでアプリを実行する。

●免責事項
本記事を参考にしたことにより生じたいかなる損害に関しても、筆者は一切の責任を負わないものとする。