2011年11月17日木曜日

【メモ】iPhoneアプリケーションの読み込み順序


●最初にmain.mのUIApplicationクラスをインスタンス化
●info.plistを読み込み、main xib file base nameからxibファイルを探す
●xibファイルを読み込み、記述に従いインスタンス化(今まではMainWindow.xibを読み込み、そこからViewControllerのxibファイルをロードしていたが、XCode4.2からAppDelegate.mに該当のソースが追加され、MainWindow.xibがなくなってしまったようです。これに2-3日はまりました)

2011年11月10日木曜日

XCodeでビルド後、iPhoneで実行する前にDon't know how to run. Try "help target" というエラーが出る件

Don't know how to run. Try "help target" というエラーが出てはまったので直った方法をシェア。
●試したこと
クリーニング
XCodeの再起動
プロパティの見直し
コンパイラの変更
→どれもうまくいかず。。
●直った方法
実機のポータルへの登録しなおし


アクセサ

インスタンスの値や属性を見たり変更したりするためのメソッドを作って使うのが流儀。
該当インスタンスの値を直接みたり変更するのではなくメソッドを作って変更する。

値や属性などを確認するのがゲッタ(getter)
値や属性を変更するのがセッタ(setter)
という名前としてつけられてる。
例)
num1 num2 num3というインスタンス変数があった場合の
num1だけ見たり変更したりするゲッタセッタ
-(int)num1{return num1;) //ゲッタ(ただnum1の値を返す)
-(void)setNum1 : (int)newvalue{
num1 = newvalue; //セッタ(num1の値をnewvalueに変更)
}

アクセサは@property @symthesizeを書くことで同様のことができる。
@propertyの書き方
例)
@property (retain,nonatomic) (id) *count;
のように属性などをつけて定義する。
アクセサを作る対象がオブジェクトの場合、retain nonatomicはつけるのが慣例
nonatomic とretainについて後で確認。
この例のretainは使用中はメモリから消されないようにする

あるインスタンスから他のインスタンス変数にアクセスする方法

例)obj1のval1に他のインスタンスからアクセスするには
obj1->val1
という書き方をする。
同じクラス内のインスタンスのみ利用可能。
使う場合にもクラス名でキャストしておく必要がある。

-(id)makerandnum:(mknum *)num
{
num1 = num->num2;
//mknumクラスの型にキャストされたインスタンス変数numにアクセス
}
☆インスタンス変数の使える範囲の指定
num->num1のように他のインスタンス変数を利用できるが、インスタンス変数へのアクセスできる
範囲を制限することができる。どこからでも変更、読み込みができたり、クラス内でしか読めないようにできたり。

@private
宣言したクラス内だけ利用可能
サブクラスからも使えない。
@protected
宣言したクラスとサブクラスから利用可能
何も指定しないと@protectedが適用される
@public
どこからでも利用可能
書き方
@interface num1 : num
{
id inclementvall;
@public
int decval;
@private
double outval;
int testval1;
@protected
int testval;
}
@end
というように種類ごとに定義する。

インターフェースに他のクラスを使うとき

インターフェースを定義するときに、他のクラスを型としてインスタンス変数に定義することができる。
その方法として、インターフェースを定義するヘッダファイルの最初に@class つかうクラス名
を宣言し、実処理を行うときに該当クラスのヘッダファイルをインポートする。
例)
@class class1
@interface newclass :NSObject
class1 *theclass1;
@end

//ヘッダファイル部
import "class1.h"
→使う暮らすヘッダファイルをインポートする。

型とクラス

インスタンス化するとき、id型を利用するが、特定のクラスのインスタンスということを明記することができる
クラス"class"専用のインスタンスを言うことを書きたい場合
class *x
というように*をつける。
このように生成されたオブジェクトはポインタとして生成され
class *x,*y
x = [[class alloc] val : 0];
x = y;
とした場合。xで実行した結果がそのままyに引き継がれる。

継承して新しく作ったクラスは、スーパークラス用に定義されたクラス名に入れることができる
例) class1 *a
@interface class : NSObject
- (void)hello
@end
@implemantation
なんちゃら
@end
@interface class2 : class
-(void) hello
@end
〜
int main(void){
class *a,*b;
a = [[class alloc] init];
b = [[class2 alloc] init];
}
というようにclass1用に作ったものでも継承して作られたclass2に入れることができる。
ただし、スーパークラスで定義されたメソッドのみしか使えない。
使いたい場合は、class2の型にキャストして利用する。
例
class1 *a,*b;
a = [[class1 alloc] init];
b = [[class2 alloc] init];
[a class1onlymethod];
[b class1onlymethod];//class2でclass1から継承したclass1にあるメソッドを利用してもエラーでない

[b class2onlymethod];//オーバーライドしたものはエラーが出る
[(class2 *)b class2onlymethod];//class2用の型にキャスト

テクニック
if文の条件の評価順序をうまく使い、インクリメントや文字列の評価をする
例)if (p && *p)
pが空の場合はそれ以降の評価は行われない。
ポインタのpかどうか調べる際、pが空だとコンパイラが落ちるので落とさずに値の評価ができる

継承とクラス

[self]でクラス自身のメソッドを呼び出したとき、上書きされていない継承したメソッドを呼んだとき
スーパークラスのメソッドが呼ばれる。
スーパークラスのメソッド内で[self]でメソッドが呼ばれたとき、スーパークラス内のメソッドが参照されるのではなく、自分のクラスのメソッドが呼ばれる(オーバーライドされたものが呼ばれる)


実装手順
ヘッダーファイルにインターフェースを書く
mファイルに実処理を@implementation以下にインターフェースに対応した処理を書いていく

実行プログラム上で書いた処理の呼び出しを行う
@interface
-変数やクラス名定義
@implementation
-色々処理
int main(void)
{
id x = [[newinstance alloc] init];//インスタンス生成
[x method1];//インスタンスのメソッド呼び出し
}
外部からのメッセージで動くメソッドの場合はinterface部分にメソッド名を定義する必要があるが
そのクラス内部でしか使わない内部用のメソッドの場合はインターフェースは書かなくてもよい。
[self]で呼び出してつかったりする。
例)カウンターアプリでダウンアップそれぞれメソッドを作るが、アップダウンと同時に音を鳴らせる場合、内部で音を鳴らせるメソッドを作成し、[self]で呼び出すなど
この場合、最初の部分に定義する必要がある([self]で呼び出される前に定義)