はじめに
Objective-CはJavaよりも古くからあり、最近ではSwiftという言語でもiOSアプリを開発が可能となりました。
ですが、既存アプリの改修や、Objective-Cを使わなければならない場面もあるため、
習熟はObjective-Cから入った方が良いと思います。
このメモの目的と注意点
私はもともとASPからプログラミングを学び、業務では主にJavaを使用していました。
現在はWEBエンジニアとしていろいろ言語には触りますが、知識としてはかなりJavaよりだと自負しています。
後輩や、新人がこれからiOSアプリを制作するにあたって、先ず読んでもらいたいと思う情報をまとめよう!
という事でこのメモを作成しています。
少しでもそういう方の役に立てればと思い、投稿します。が、書きかけです。
のんびり書いていこうと思います。
Xcodeについて
XcodeとはAppleが提供してくれているIDE(統合開発環境)です。
Objective-CのコンパイルからApple Store申請、ipaファイル書き出しなど、
様々なサポートを行ってくれるソフトウェアです。
現在、XcodeがWindows上で動作しないため、Macでの開発が必須となっています。
Xcodeは現在3つのバージョンがあります。
Xcode4.6.3 Xcode5.x Xcode6 beta の3種類です。
新規アプリの開発などには Xcode5.x (現行の最新安定版) を利用します。
Xcode4.6.3 環境で作成したアプリに関しては Appleによりリジェクト対象となっています。
(すなわち、申請する必要のないアプリに関しては4.6.3でも構わないという事でもあります。)
Xcode6 beta は文字通りβバージョンではあります。
2014年秋にiOS8と同時期にリリース予定であり、リリース後はXcode6を利用することになるでしょう。
(AppleがそのうちXcode5でビルドしたアプリをリジェクト対象にしてしまうため。)
Xcode4.6.3について
現在の最新である OS X 10.9.3 では動作しません。
OS X 10.9.3未満 を所持している方は極力アップデートを避けましょう。
構文
コンパイラはCと同じ
gccコマンドでコンパイルできます。(Xcodeがやってくれるので意識しなくても良いですが)
C言語に触ったことのない人で、最も理解に苦しむのはポインタ(*)だと思われます。
@
ではじまる構文
これらはコンパイラディレクティブと呼ばれるものになります。
宣言とか
@interface
@implementation
@protocol
@end
インスタンス変数のスコープ
@private
@protected
@public
例外処理
@try
@throw
@catch
@finally
その他
@class
@selecter()
@protocol()
@encode()
@defs()
@"文字列"
@synchronized
宣言
クラスの定義
下記の例では
setNumber
getNumber
というアクセサを実装していますが、
実際には@property
と@synthesize
を利用している場合、以下の様な実装は必要ありません。
@interface SampleClass : SuperSampleClass <SampleProtocol>
@property (retain, nonatomic) int number;
- (int)getNumber;
- (void)setNumber:(int)value;
@end
@implementation SampleClass
@synthesize number;
- (int)getNumber {
return self.number;
}
- (void)setNumber:(int)value {
self.number = value;
}
@end
Objective-cはC言語と同じく、2ファイルで構成されています。
ヘッダーファイル(拡張子:h)とメインファイル(拡張子:m)で、ヘッダーファイルは主に定義を記述し、
実装部分はメインファイルに記述します。
- @interface クラス名 : 継承するクラス名 < **採用するプロトコル** >
プロトコルについては後述します。
プロパティ
- @property ( 属性 ) (IBOutlet) プロパティの型 プロパティの名前
属性
属性 | 意味 |
---|---|
readonly | 読み取り専用。ゲッタメソッドのみ生成 |
readwrite | 読み書き可能(デフォルト。省略可)セッタメソッド、ゲッタメソッド共に生成 |
copy | 引数の値をコピーして渡す |
atomic | インスタンスの同時実行をさせない。が怪しい(デフォルト、省略可) |
nonatomic | 基本的にatomic は指定せずにこちらを指定し、インスタンスの同時実行をさせない場合は別途処理を記述する必要がありそう |
assign | retainを実行しないで単純に代入する(ARCの__unsafe_unretainedと同じ意) |
getter= | ゲッタメソッド名を変えたい場合 |
setter= | セッタメソッド名を変えたい場合(引数がつくため、最後に:(コロン)が必要) |
strong | ARCの強い参照と同じ意 |
retain | ARCの強い参照と同じ意 |
__weak | ARCの弱い参照と同じ意 |
assign, retain, copy でアクセサを合成した場合は、それぞれ下記の様な実装になる。
// assign
property = newValue;
// retain
if (property != newValue) {
[property release];
property = [newValue retain];
}
// copy
if (property != newValue) {
[property release];
property = [newValue copy];
}
IBoutletとは
IBOutletを宣言し、InterfaceBuilderと接続したプロパティ(またはインスタンス変数)は、
初期化の際に接続したインスタンスを初期化の段階で設定してくれます。
プロパティとインスタンス変数について
この辺は自分で調べてみてください。
プロパティを上記方法で記述すると、インスタンス変数も生成されます。
スコープ
インスタンス変数を定義する場合は、スコープを設定可能です。
スコープとは可視範囲という意味で、3つの種類が用意されています。
- private
- protected
- public
private
privateとは、定義したクラスでしか扱う事ができません。
インスタンス化した際はもちろん、定義したクラスを継承した場合でも、privateで宣言したものは参照できません。
protected
protectedは、privateから少し範囲が広くなり、定義したクラスを継承したクラスで参照できるようになります。
この継承には制限がなく、子でも孫でも、それ以下でも参照可能となります。
public
さらに範囲が広がり、publicにはスコープによる可視範囲の制限がなくなります。
プロパティは確はprivateだった気がします。
が、アクセサメソッドが自動生成されるので、あんまり気にしなくても構いません。
(実装部に @synthesize
を設定した場合)
メソッド
- ( 戻り値の型 ) メソッド名 :( 引数の型 ) 引数の変数名
メソッドは上記の様に記述します。
戻り値を省略する場合は、戻り値の型を void
と設定します。
クラスメソッドとインスタンスメソッド
クラスメソッドとインスタンスメソッドは、メソッド定義の先頭で指定します。
先頭 | 意味 |
---|---|
+ | クラスメソッド |
- | インスタンスメソッド |
引数の数による違い
Objective-Cのメソッドは他の言語ではあまり指定しない、引数のラベルを指定します。
これは引数が2個以上の場合に指定します。
// メソッドの定義
- (void)countUp;
// メソッドの実行
[self countUp];
// メソッドの定義
- (void)countUp:(int)value;
// メソッドの実行
[self countUp:1];
// メソッドの定義
- (void)countUp:(int)value max:(int)maxValue;
// メソッドの実行
[self countUp:1 max:10];
プロトコルの定義
プロトコルとは メソッドのみを定義したもの となります。
プロトコルはクラスではありませんので、オブジェクトはなく、もちろんインスタンス化もできません。
したがってプロトコルはヘッダーファイルのみ存在します。
プロトコルの用途は、クラスに対して必要なメソッドを定義しておき
クラスで採用して使用します。
例)
プロトコル名:電話プロトコル
所持機能 :音声の送信、音声の受信
この様なプロトコルを定義し、実際に電話機としてのクラスを作成する場合、
このプロトコルを採用します。
そうすることによって、電話プロトコルを採用しているクラスは最低限、
上記で定義した機能を所持しているという状態が保証されます。
型を指定して使用はできないが、機能のみを特定して処理を行いたい場合、
id<TelProtocol>
の様にプロトコルを指定してやることで、id
型のまま定義した機能を利用する事が可能となります。
@protocol ProtocolName
- (void)requiredMethod;
@required
- (void)requiredMethodTwo;
@optional
- (void)otherMethod;
@end
プロトコルは継承することも可能です。
@protocol ChildProtocol <SuperProtocol>
@end
プロトコルとは、Javaではインターフェイスと呼ばれています。
Javaではインターフェイスは実装して利用していましたが、
Objective-Cでは 採用する と呼ぶそうです。
@interface Class <ChildProtocol>
// 複数のプロトコルを採用剃る場合
@interface Class <ChildProtocol, OtherProtocol>
ステートメント
データ型
データ型 | 意味 |
---|---|
int | 32ビット 符号付き整数型 |
unsigned int | 32ビット 符号なし整数型 |
long | 32ビット 符号付き整数型 |
unsigned long | 32ビット 符号なし整数型 |
short | 16ビット 符号付き整数型 |
unsigned short | 16ビット 符号なし整数型 |
char | 8ビット 符号付き整数型(1文字を格納) |
unsigned char | 8ビット 符号なし整数型(1文字を格納) |
float | 32ビット 浮動小数点数型 |
double | 64ビット 浮動小数点数型 |
BOOL | 真偽値型(YES or NO) |
NSInteger | 32ビット 符号付き整数型 |
NSUInteger | 32ビット 符号なし整数型 |
NSDecimal | 160ビット 浮動小数点数型 |
上記以外は基本的に参照型となります。
long, NSInteger, CGFloatなどは64ビット向けにコンパイルすると64bit長になりますので注意が必要です。
参考:http://d.hatena.ne.jp/nakamura001/20130929/1380450561
変数の宣言
変数の宣言は特殊なところはありません。
- 型 変数名
int age;
NSString* name;
NSString *address;
NSString * girlFriendName;
id child;
id
が汎用オブジェクトでも言いましょうか、どのクラスでも収容できる型となります。
参照型を宣言する場合は上記の様にアスタリスク(*)を付けなければいけません。
id
型には必要ありません。
(型、変数名のどちらかにつけるかは好き好きみたいです。たぶん。)
分岐
条件については、他言語とそんなに違いはありません。
a == b
a != b
a && b
a || b
!a
どれも使えます。
// 基本構文
if (a == 1) {
// a == 1 が成立した際の処理
}
// 分岐
if (a == 1) {
// a == 1 が成立した際の処理
}
else if (a == 2) {
// a == 1 が成立せず、a == 2 が成立した際の処理
}
else {
// a == 1 が成立せず、a == 2 も成立しなかった際の処理
}
// 三項演算子
// a == 1 が成立した場合は one が、しなかった場合は other が代入される
NSString *str = (a == 1) ? @"one": @"other";
switch(integer){
case 1:
// integer == 1 が成立した際の処理
break;
case 2:
// integer == 2 が成立した際の処理
break;
default:
// 上記の処理をbreakで抜けない限り、常に処理
break;
}
ループ
continue
break
共に以下のステートメントで利用できます。
// i を 0 から 9 まで 10回 ループさせる
for(int i = 0; i < 10; i+){
// 処理
}
// コレクションのループも用意されています
NSArray *array;
for(NSString *str in array){
// 処理
}
while (a == 1) {
// a == 1 が成立する間、常に処理
}
// do-while構文
do {
// a == 1 が成立する間、常に処理されるが、初回は必ず処理する
} while (a == 1);
ブロック構文
書きかけです!