Objective-C と Xcode
Objective-C
すべての言語仕様について記述しているわけではありません。
基本
id
- Objective-Cでは、どのクラスに属していても、オブジェクト識別子は id というデータ型で表現できる。
nil
- NULLオブジェクト
BOOL
- 真偽を表現できる。YES/NO の値を取る。(true/false ではない)
SEL
- メソッド名を識別する為のセレクタ
文字列
- 基本 NSStringという文字列クラスを利用する。
動的型
- すべてのオブジェクトがオブジェクトのクラスを示す isaインスタンス変数を持ち、オブジェクトの情報にアクセスができる。
#import
ヘッダー(宣言)ファイルを読み込む。同じファイルを何度指定しても実際に読み込まれるのは1度だけです。
オブジェクトとメッセージ
あるクラスのインスタンスの生成(オブジェクト)は、 alloc を呼びます。
SomeClass *instance = [SomeClass alloc];
通常、直後に初期化を行うメソッドを呼びます。init, initWithA:B: のように init ではじまるメソッド名にします。
SomeClass *instance = [[SomeClass alloc] init];
オブジェクトobj の持つメソッド doSomeThing を実行するには以下のように記述します。
[obj doSomeThing];
これはメッセージ式とよばれ、レシーバーobj にメッセージdoSomeThing を送ると表現することもあります。メッセージ式は、メソッドの実行結果を返します。もし結果がオブジェクトであれば、以下のように続けて記述できます。
[[obj returnObjSomthing] doSomeThing];
引数を持つメソッドを実行するには以下のように記述します。
[rectangle setWidth:300 andHeight:125];
英文を書くような感じで記述できるようするため、引数の前にキーワードを付けて記述します。
クラスの書式
宣言(.h ヘッダーファイルに記述、クラス名は大文字ではじまり、メソッド名は小文字ではじまるキャメルフォーマットにするのが習慣です。)
// 宣言 @interface ClassName : SuperClassName <ProtocolDelegate> { NSString *name; MyViewController *_instanceValiable; } // アクセサメソッドを生成したいインスタンス @property (nonatomic, retain) MyViewController *instanceValiable; // アクセス可能なメソッド - (id)initWithString:(NSString *)aName; - (void)methodWithParameter:(int)param1 paramName:(int)param2; + (ClassName *)createMyClassWithString:(NSString *)aName; @end
実装(.m ソースファイルに記述)
#import "ClassName.h" // 実装 @implementation ClassName // アクセサメソッドの生成 @synthesize instanceValiable = _instanceValiable; // イニシャライザー - (id)initWithString:(NSString *)aName { self = [super init]; if (self != nil) { name = [aName copy]; } } // デストラクタ - (void)dealloc { [name release]; [super dealloc]; } // インスタンスメソッド - (void)methodWithParameter:(int)param1 paramName:(int)param2 { NSLog(@"param1=%d, param2=%d", param1, param2); } // クラスメソッド + (ClassName *)createMyClassWithString:(NSString *)aName { return [[[self alloc] initWithString:aName] autorelease]; } // プライベートメソッド(宣言部に記述していないメソッド。。。厳密な意味でプライベートなわけではない) // プライベートなメソッドは、宣言より前で利用することが出来ません。(カテゴリという機能を利用すると可能) - (void)privateMethod() { } @end
プロパティー
属性 | 内容 |
---|---|
readonly | ゲッターのみ利用可能 |
readwrite | ゲッター/セッターが利用可能 |
assign | セッター時単独代入 |
retain | セッター時にメモリ領域を確保 |
copy | セッター時にオブジェクトのコピーを行う |
noatomic | ゲッター/セッターから返される値は、他のスレッドが同時に実行してるかどうかに関わらず完全に取得/設定される。複数のスレッドから同時に読み込まれた際の動作補償は無い。 |
アクセサの利用方法は、以下のどちらを利用しても良い。
[obj value]; // ゲッター(get) obj.value; // ゲッター(get) [obj setValue:val] // セッター(set) obj.value = val; // セッター(set)
クラスの拡張はサブクラスを作成するのが一般的だが、メソッド呼び出しのオーバーヘッドが増えたり、既存のインスタンスを拡張することはできない。しかし、Objective-Cではカテゴリという機能でメソッドを追加することができる。
Objective-Cも、多重継承はサポートしておらず、プロトコルという Javaのインターフェースと同等の機能が用意されています。 任意のクラスで実装される可能性のあるメソッドを@protocol, @endで宣言しておく必要があります。
メモリ管理
Objective-C のメモリ管理は、インスタンスの参照が増えると参照カウンタがインクリメントされ、参照が減るとデクリメントされる、カウント式で管理される。参照カウンタが 0 になると dealloc が呼ばれる。(Objective-Cには、ガーベージコレクションがあるが iOS では利用できない)
メモリ確保方法 | 解放方法 |
---|---|
autorelease | 自動で解放される |
retain | releaseを記述した任意のタイミング |
注意点
- ● 自分が alloc, copy, retain したオブジェクト以外は release しては行けない
- ● 他人の作成したオブジェクトを自分が保持し続けたいなら retain する
- ● 自分が retain したオブジェクトは必ず release する
数値
int | 12300 |
float | 1.53f |
double | 0.12345 |
文字列
文字列 | NSString *string = @"文字列だよ"; |
文字列の長さ | int length= [string length]; |
文字列比較 | BOOL isEqual = [string isEqualToString:@"比較文字列" |
文字列抽出 | NSString *sub = [string substringWithRange:NSMakeRange(2,3)]; |
配列(変更不可能)
インスタンス生成 | NSArray *array = [NSArray arrayWithObjects:@"item1", @"item2", @"item3", nil]; |
要素数の取得 | int count= [array count]; |
要素の取得 | id obj = [array objectAtIndex:0]; id obj = [array lastObject]; NSArray *subArray = [array subarrayWithRange:[NSMakeRange(0,2)]; |
要素のインデックスを取得 | int index = [array indexOfObject:@"item2"]; |
要素が含まれているか確認 | BOOL isContain = [array containsObject:@"item6"]; |
配列(変更可能)
インスタンス生成 | NSMutableArray *array = [NSMutableArray array]; |
要素の追加 | [array addObject:@"ABC"]; [array addObject:someObject] |
要素の削除 | [array removeObjectAtIndex:0]; [array removeLastObject]; [array removeObjectsInRange:[NSMakeRange(1,2)]; |
要素のインデックスを取得 | int index = [array indexOfObject:@"item2"]; |
要素が含まれているか確認 | BOOL isContain = [array containsObject:@"item6"]; |
連想配列(変更不可能)
インスタンス生成 | NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:@"item1", @"key1", @"item2", @"key2", @"item3", @"key3", nil]; |
要素数の取得 | int count= [dic count]; |
要素の取得 | id obj = [dic objectForKey:@"key2"]; |
すべてのキーを取得 | NSArray *array = [dic allKeys]; |
すべての要素の取得 | NSArray *array = [dic allvalues]; |
連想配列(変更可能)
インスタンス生成 | NSMutableDictionary *dic = [NSMutableDictionary dictionary]; |
要素の追加 | [dic setObject:@"item4" forKey:@"key4"]; |
要素の更新 | [dic setObject:@"change4" forKey:@"key4"]; |
要素の削除 | [dic removeObjectForKey:@"key2"]; [dic removeAllObject]; |
高速列挙
// 配列 NSString *element; for (element in array) { NSLog(@"element - %@", elemnt); } // 連想配列 NSString *key; for (key in dic) { NSString *val = [dic valueForKey:key]; NSLog(@"%@ = %@", key, val); }
ファイルアクセス
// パス NSString *path = @"/path/to/filename.txt"; NSFileHandle *file; // 読み込み file = [NSFileHandle fileHandleForReadingAtPath:path]; NSData *data = [file readDataToEndOfFile]; [file closeFile]; // 書き込み file = [NSFileHandle fileHandleForWritingAtPath:path]; NSData *data = [file writeData:data]; [file closeFile];
Xcode
気になる機能を抜粋
Xcodeを利用するにあたり
改行は \n | 日本語キーボードで¥ではなく、バックスラッシュを入力する方法は Option + ¥ |
EXEC_BAD_ACCESS | NSZombieEnabled, MallocStackLogging, NSDebugEnabledを YES にする。 Xcode4 の場合、Product > Edit Scheme...を選び、Run XXXX の Argumentsタブ > Environment Variableに追加する。 この設定で実行し EXEC_BAD_ACCESSが出たら shell malloc_history [PID] [インスタンスのアドレス] を gdb で実行する。 |
ターゲットとデリゲート
アプリケーションデリゲート | 内容 |
---|---|
applicationDidFinishLaunching | アプリケーションが起動したときに呼び出される |
applicationDidBecomeActive | アプリケーションがアクティブになったときに呼び出される |
applicationWillResignActive | アプリケーションが非アクティブになったとき呼び出される |
applicationWillTerminate | アプリケーションが終了するときに呼び出される |
※ UIKit関連は時間に余裕が出来たら追加していく予定。。。