(macの)Ojbective-Cの勉強メモ。
自分用なので他の人が見ても役に立たないかも。
自分用なので他の人が見ても役に立たないかも。
- クラス宣言
@interface クラス名 : スーパークラス名 <プロトコル名> { 型 変数名; // インスタンス変数 IBOutlet 型 変数名; // アウトレット } + (返値の型)メソッド名; // +で始まるとクラスメソッド - (返値の型)メソッド名; // - で始まるとインスタンスメソッド - (返値の型)メソッド名:(引数の型)仮引数名; // 1引数のメソッド - (返値の型)メソッド名:(引数1の型)仮引数名1 ラベル2:(引数2の型)仮引数名2; // 2引数以上のメソッド - (IBAction) メソッド名:(id) 仮引数名; // アクション @end
<プロトコル名>は省略可能。多重継承はできない。プロトコルは複数実装できる。(,区切りで並べる)
疑問: 省略可能引数は?
→できなさそう。ただし、...とva_*マクロは使える。 - クラスの実装
@implementation クラス名 - (返値の型)メソッド名:(引数の型)仮引数名 { // メソッドの実装 } @end
- 宣言は*.hに、実装は*.mに書く。#includeの代わりに#importを使う。
- メソッドの呼びだし
[オブジェクト メソッド名]; // 引数なしのメソッドの呼びだし [オブジェクト メソッド名:実引数]; // 引数1個のメソッドの呼びだし [オブジェクト メソッド名:実引数1 ラベル2:実引数2]; // 引数2個以上のメソッドの呼びだし
オブジェクトの所にクラス名を書くとクラスメソッドの呼びだし。
疑問: ラベルの順番は宣言の通りでないといけないの? - idはNSObject *のエイリアスだと思っておいて良い
→まずいらしい。 - インスタンスの生成
id object = [[クラス名 alloc] init]; // allocはNSObjectのクラスメソッド、initはNSObjectのインスタンス // メソッド両方とも返値の型はid。この段階で参照カウンタは1。 object = [object autorelease]; // 自動解放のマーク。
initには引数付きのいろいろなバリエーションが存在し得る。また、allocとinitとautoreleaseをセットでやってくれるようなクラスメソッドも提供されている場合がある。 - インスタンスの解放
インスタンスは、releaseの呼びだしによって参照カウンタが0になると解放される。このとき、deallocと言うメソッドをオーバーライドしてあれば、それが呼ばれる。オーバーライドしたら[super dealloc]を呼ぶ。 - releaseの反対はretainで、参照カウンタを1増やす。NSArrayなどのコンテナに入れた場合はそこでretainされるので、あまり自分でretainを呼ぶ機会はないか?
→インスタンス変数がオブジェクトなんかの場合に、setterでコピーしない場合はretainする。 - autoreleaseの呼び出しは、インスタンスのNSAutoreleasePoolへの登録。NSAutoreleasePoolは、Cocoaのイベントループ毎に再生成されるので、autoreleaseしたオブジェクトの寿命はイベントハンドラの実行が終わるまで。
- 文字列
NSStringは変更不可能な文字列、NSMutableStringは変更可能な文字列。内部エンコーディングはUTF-8? - 文字列リテラル(NSString)
NSString *string = @"hogehoge";
※ 参考にした本では、@""の中には日本語が書けないと書いてあったが、Xcode4でUTF-8のソースであれば日本語を書いても普通に通った。 - カテゴリの宣言
@interface 既存クラス名 (カテゴリ名) //メソッドの宣言 @end
カテゴリは、既存のクラスにメソッドを追加する。 - カテゴリの実装
@implementation 既存クラス名 (カテゴリ名) //メソッドの実装 @end
- プロトコル
@protocol プロトコル名 <スーパープロトコル> //必須メソッドの宣言 @optional //オプションメソッドの宣言 @required //必須メソッドの宣言 @end
Javaのinterfaceのようなもの。多重継承可。継承が必要ない場合でもクラスは必ずNSObject(Ojbect)のサブクラスにするが、プロトコルは継承元がなくても良い。
- プロトコルの利用
プロトコルは、クラスの宣言時にそのクラスがそのプロトコルを実装していることを表す他に、変数の型やメソッドの引数/返値の型に使える。id
これらはコンパイル時に静的な型チェックが行われる。hoge; // プロトコルHogeを実装したクラスのインスタンスを入れられる変数 hoge - (void)setHoge:(id )hoge; // Hogeを実装したクラスのインスタンスのsetter hoge = @"hoge"; // NSStringはHogeを実装していないのでエラー [obj setHoge: @"hoge"]; // 同上
- 言語としての@protocolではなく、NSObjectのカテゴリとして宣言したものを、非形式プロトコルと呼ぶ。
非形式プロトコルはコンパイル時の型チェックが行われない。
Cocoaのdelegateなどで利用されている。これは、Objective-C 2.0より前のバージョンでは、@protocolに@optionalがなかったため、全てのプロトコルのメソッドを実装しなくても良いものとして使われていたらしい。 - 宣言プロパティ
@interface クラス名 { 型 プロパティ名; } @property (属性) 型 プロパティ名; @end @implementation クラス名 @synthesize プロパティ名; @end
- @propertyはクラスがプロパティ名で示されるプロパティを持つことの宣言であり、メンバ変数として持っている必要はない。
- 属性には、以下が設定できる
- getter=ゲッタ名: getterメソッドの名前を変えるとき
- setter=セッタ名: setterメソッドの名前を変えるとき
- readonly: getterのみ
- readwrite: getterとsetter(デフォルト)
- assign: 単なる代入をするsetter(デフォルト)
- retain: retainするsetter
- copy: copyするsetter
- nonatomic: スレッドセーフにしないとき
- 実装部分に@synthesizeを書くと、自動でgetterとsetterが生成される。@synthesizeを書かずに自分で実装しても良い。自動生成する場合は、プロパティと対応するメンバ変数が必要。
- メンバ変数名とプロパティ名を変えたい場合は、
@synthesize プロパティ名 = メンバ名;
のように書く - 宣言プロパティは、以下のように二つの方法でアクセス可能
[obj setXxx:value]; // setterメソッドの呼びだし obj.xxx = value; // .演算子によるアクセス value = [obj xxx]; // getter メソッドの呼びだし value = obj.xxx; // .演算子によるアクセス
- オブジェクト型のプロパティの場合で、assign又はcopyを指定したときは、releaseの責任を持つことになるので、deallocをオーバーライドしてreleaseしてやらないとリークする
カテゴリ
プログラミングトラックバック(0)
このブログ記事を参照しているブログ一覧: Objective-C メモ
このブログ記事に対するトラックバックURL: https://www.wizard-limit.net/cgi-bin/mt/mt-tb.cgi/2682
コメントする