完全なC互換。CocoaはObjective-CのAPI。Cocoaについて学べば必然的にObjective-Cについて学べます。主な開発環境はXcode(または旧Project Builder)。プログラミング言語

目次

新版(構成豫定圖)

Objective-C

一般的な Object 指向の思想を理解してゐる前提の元に文法事項を解説。全てを粒さに讀む必要はない。Cocoa の方をやりながら文法事項を知りたいなと感じれば、外國語の學習同樣に、必要な時に必要な所を參照した方がよい。

豫め定義された型と變數

Objective-C では新たに次の樣な型が定義されてゐる(objc-class.h)。

言語構造上の變數は

など馴染みの物がある。これらは一例に過ぎないし全てを遣ふわけではないから、追々説明する事になるだらう。

クラス(class)

定義は.hファイル、實裝は.mファイルに書く。Xcode で新たに書類をプロジェクト追加する際に、Objective-C Class テンプレートを選ぶと、.hファイルと.mファイルが自然に追加される。

// MyObject.h
@interface MyObject : NSObject{
}
@end
// MyObject.m
@implementation MyObject
@end

Objective-C では C と區別(或いは將來の互換性確保)の爲に、擴張した文法は@を附け記述する(ディレクティブ參照)。今この記述では、NSObject を繼承した MyObject クラスの定義をした事になる。

註:新たにクラスを定義する場合は、一般に NSObject を繼承したクラスを定義する。その理由は NSObject が Cocoa における一般的な手續きを全て網羅してゐるからである。またその他のクラスに於ては、特段の理由や意味がない限り、サブクラスを造らない方が良い(譬へば NSString や NSArray のサブクラスを作製しても思ふ樣にはいかないだらう)。逆に能くサブクラスを作るのは、NSObject の他に、稀だが NSApplication の場合や、或いはサブクラスを作る爲のクラス NSManagedObject 等である。

よくサブクラスを作るスーパークラスの例

目的別に使ひわけることになる。

命名規約(クラス)

クラスは大文字で始めねばならない。Objective-C は 大文字と小文字を峻別する。今幾つかクラス名を擧げてきたが、自身のクラスを作る際に NS を接頭辭としてはならない。NS は NeXTSTEP の略であり、今では Apple による API を區別する爲のクラス名接頭辭として「豫約」されてゐる規約である。注意して欲しい。他にも IO(Input-Output)や OS(Operating System) や CG(Core Graphics)等 API 系により、ある程度の先客があるので、紛らはしい名前は避けた方がよい。

メッセージ(message)或いはメソッド(method)

今先程のクラスに、インスタンス變數 obj、クラスメソッド myClassMethod、メソッド myMethod を追加したとすると、

// MyObject.h
@interface MyObject : NSObject{
   id obj;
}
+(void)myClassMethod;
-(id)myMethod;
@end
// MyObject.m
@implementation MyObject
+(void)myClassMethod
{
   /// your code
}
-(id)myMethod
{
   return obj;
}
@end

ヘッダにおける括弧の遣ひ方に注目して欲しい。括弧はインスタンスが保持する變數を記述する箇所で、メソッドを記述する箇所ではない。クラスメソッドは+、インスタンスメソッドは-で書き始める規則がある。以後メソッド名と共にクラスメソッドかインスタンスメソッドかを示す際には ± を以て明示する事にする。

さてメソッドは、@ の圍み、@interface ~ @end@implementation ~ @end に於て記述する。文字通り定義と實裝を表す。なほ Objective-C は完全な Object 指向を目指す物ではなく實用を任とする言語であり、Ruby の Kernel Object 樣な物は無く、詰り通常の函數は C と同じ方法で定義し利用できる。だから圍みの外で函數を定義するとよい(註:C のコードとは共存できる)。

今、更にこの MyObject のインスタンスを保持した變數 receiver が存在したとすれば、二つのメソッドを呼出すには、

[MyObject myClassMethod];
[receiver myMethod];

と書く(結果を取得するなど變數の扱ひは C と全く同じなので略)。Objective-C に於てインスタンスをレシーバと呼ぶが、その意味は、Objective-C に於けるメソッドの呼出され方・動作に由來する。一般に「レシーバにメッセージを送る」と謂へば、インスタンスメソッドを起動する事を意味する。

註:id型はObjective-Cに於て新たに定義された型の一つで、任意のレシーバを表す型である。この樣な汎用的な型については附録參照。

引數

引數を渡すには幾つか規則が存るが、先づ單純な一つ渡す方法を示す。今 id 型の變數 value を -myMethod に渡すとして、

[receiver myMethod:value];

と書く。メソッド名の後に :(コロン)を打つて引數を書くと、レシーバにメッセージが送信される。上の定義と實裝を書き直せば、

// MyObject.h
@interface MyObject : NSObject{
   id obj;
}
+(void)myClassMethod;
−(id)myMethod:(id)val;
@end
// MyObject.m
@implementation MyObject
+(void)myClassMethod
{
   /// your code
}
−(id)myMethod:(id)val;
{
   return obj;
}
@end

更に複數の引數を渡したいのならば、可變長かラベルを利用する事になる。

註:Xcode で Cocoa アプリケーションを開發するならば、メソッドを呼び出す時は、ヘッダが解析された後に入力支援システムによつて補助が入り、どこにコロンを打ちどこにどんな變數がと云ふ事を惱む必要がなくなる。だから今一番憶えておきたいのは、寧ろメソッドの記述方法である。

可變長引數

C における可變長と同じく、可變長引數を id 型にすれば

+(void)myClassMethod:(id)objects, ...;

と書ける。

ラベル(label)

Objective-C で尤も一般的な複數引數の記述・利用法がラベルである。Objective-C では、その他の言語での引數がただの變數の羅列になるのとは對蹠的に、引數に名前を指定する。この名前をラベルと謂ふ。座標を渡すメソッドを考へたならば、

[receiver myMethod:val withX:x withY:y];
−(id)myMethod:(id)val withX:(int)x withY:(int)y;

と書く。ラベルの導入は code を著しく簡明にする。C の函數等で myMethod(val,num1,num2); と書くと引數の意味が取りづらいが、Objective-C では上にある樣に見目に分り易くなつてゐる。詰り打鍵數は増えるかもしれないが、それでもなほ利點が大きいと判斷された爲に、ラベルは導入されたのである。

またこのラベルは同じメソッドで幾通りも用意できる。今上に示した樣なメソッドはドキュメント等では myMethod:withX:withY: と書く事で略記されてゐるが、myMethod:withX:withY:withZ: なるメソッドを作りたいと思つた時、myMethod:withX:withY: と myMethod:withX:withY:withZ: は共存できる。

註:一つだけの引數の場合はラベルがない樣にみえるが、次の樣な解釋ができる。卽ち上のメッセージは「myMethod:、withX:、withY: と云ふ三つのラベルを有してをり、myMethod: の如きメソッド名の樣にみえる表記はラベルを表してゐるに過ぎぬ」と謂ふ物である。つまりレシーバに引數を送信する爲には必ずラベルをつけたメッセージを送るとみれるわけ。なほラベル自體は文法上必須ではなく、メソッド名だけでも良いが、上に擧げた「見目に分り易い」ことが重要なのである。

メソッドの上書き(override)

Objective-C は柔軟すぎる言語である。中にはかなり邪惡或いは病的な手段も存在するが、それらの使用は全てプログラマ委(まか)せとなつてゐる。これは Objective-C が弱い型附けである事と同じ理由であらう。今は親クラス(superclass)のメソッドを上書き(override)する方法を示す。

<準備中>

註:上書きする場合はいちいちヘッダに書く必要は無いが、若し書きたいと思ふのなら、書いても問題はない。

命名規約(メソッド)

Cocoa API を見て行くと暗默上の諒解が幾つもある。この事はもう少し後に扱ふべき内容であるから、API をみて何かあると感じた時、規約がある事を思ひ出して欲しい。

今 NSString のメソッドを例にすると、

  1. + stringWithString:, + stringWithUTF8String:, etc.
    特別なファクトリメソッド(簡易コンストラクタと謂ふ)であり、戻り値は初期化されてゐる。接頭辭は何のオブジェクトによるが、number や array 等多岐にわたる。
  2. − initWithString:, − initWithUTF8String:, etc.
    特別なイニシャライザ(指定イニシャライザと謂ふ)である。init で始める。ファクトリメソッドも含め、初期化手段を複數用意する場合には實態を一つに限らねばならない。初期化については後述。
  3. − doubleValue, − dataUsingEncoding:, etc.
    これも一つのファクトリメソッドだが、面白いのは NSString 以外の値を返す事と、これがインスタンスメソッドである點である。前者は double、後者は NSData を返す。上であげた命名規則と比べて欲しい。
  4. − writeToFile:atomically:encoding:error:, − writeToURL:atomically:encoding:error:
    writeTo はデータを書き出すメソッド名である。データは NSData にするのが一般的。
  5. − isAbsolutePath
    眞僞値を返す場合に is で書き始める。
  6. − isEqualToString:
    isEqualTo は is だけみれば眞僞値を返す例と同じに見えるが、その利用はインスタンスの比較に限る。NSObject のメソッドを參照。
  7. − getLineStart:end:contentsEnd:forRange:, − getCString:maxLength:encoding:
    get は getter の樣にみえるが、これは C のポインタを渡してインスタンスから値を取得する場合に用ゐる(詰り參照渡しの)メソッドである。
  8. − UTF8String, − length, − propertyList, etc.
    Objective-C における getter は get を用ゐない。これらが getter 的なメソッドである。一方 setter は set で書き始めても構はない。詳しくは Key-Value Coding Protocol を參照。

等が即座に指摘できる。これらは順にドキュメントを讀んだりしながら、各が會得して欲しい事項である。

レシーバ(receiver)或いはインスタンス(instance)

Objective-C におけるインスタンスは、C のポインタである。だから變數の型にはポインタを表す * が必須である。

NSObject *obj = [[NSObject alloc] init];

このインスタンスたるポインタに、Objective-C の Runtime が、メッセージを送受信してオブジェクト指向たらしめてゐる。なんとなれば、id 型は void * 型と等價であると謂ふ事だが、一つだけ違ふ點は、id 型が Objective-C のレシーバであると保證してくれる事である。だから任意のクラスのレシーバを利用したい場合は id 型を用ゐるとよい。

レシーバの初期化

レシーバの初期化は上にあげた +alloc, -init が尤も基本的な物であるが、ファクトリメソッドが用意されることもある。遣ひ分けは後々メモリ管理で論じるが、今はメモリリークは一切氣にせずに、初期化法を考へてみる。

alloc と init は NSObject(より正確には NSObject Protocol)で定義されてをり、Objective-C の根幹を成すメソッドの一つである。alloc はレシーバにメモリを割り當てるが、この alloc は上書きしてはならない。init はこれを初期化するが、自身の初期化をコードを用ゐたいならば、上書きしてもよい。

註:オブジェクトの所有權についてはメモリ管理をみて欲しい。より詳しい初期化についての事はそこで述べることになる。

nil の扱ひ

Objective-C では、nil に存在しないメッセージを送信しても、エラーが發生しない。これは通常のレシーバでは致命的なエラーとなる事と異なる結果を導くので注意して欲しい。

[nil myMethod];// エラーにならない
[receiver myMethod2]; // myMethod2が未定義ならばエラー

これは譬へば delegate で nil を設定しても呼出しに惱む必要がない等、ただメッセージを送信するだけの用途のコードのエラー處理を短縮する事になるだらう。

メモリ管理

Objective-C のメモリ管理は「參照カウント」と「ガベージコレクション」が用意される。Mac OS X はメモリリークしたメモリであれプロセス終了時に回収してくれるが、實行時にメモリを大量に利用する場合メモリ確保が困難になるかもしれない。だからなるべくメモリリークを防ぐコードを書くべきである。ここでは參照カウントにまつはるメソッド、つまり NSObject に實裝されてゐる NSObject Protocol の +alloc、-init、-retain、-release、-autorelease、そして NSAutoreleasePool class を解説する。なほガベージコレクションを利用する場合は Mac OS 10.5 以降に導入され以前のバージョンと互換性がないので注意する。

  1. alloc はメモリを割り當てたオブジェクトを返す。malloc 同樣確保に失敗すれば nil を返す。生成されるオブジェクトの參照カウント は 1 となる。
  2. init はオブジェクトを初期化する。Cocoa はこの二段構へにする事でオブジェクト生成に柔軟性を與へてゐる。
  3. retain はメモリ割り當てを解放しない爲の手續きである。參照カウントを 1 増やす。
  4. release はメモリ割り當てを解放する爲の手續きである。參照カウントを 1 減らす。

一般に上から順に實行する。Objective-C Runtime は、メソッドを實行し終はると、alloc で 生成したオブジェクトにメモリ解放するメッセージ [receiver release]; を自動的に送る。だから任意の瞬間にオブジェクトを解放したいのならば、retain によりカウンタを増し release によりカウンタを減らせばよい。release は參照カウントが 0 になればオブジェクトを解放してくれる。

autorelease と NSAutoreleasePool

上で示した仕組みでは時に問題が起る。メソッドの戻り値としてメソッドが生成したオブジェクトを返す場合である。

−(id)myMethod
{
   NSObject *val = [[NSObject alloc] init];
   return val;
}

今この樣なメソッドの戻り値を利用する場合を考へる。しかし Runtime によつて、このままでは val に release が送信され、取得した時點では既に解放されてゐる。假に retain してみればどうなるであらうか・・・・。

簡易コンストラクタ

簡易コンストラクタは autorelease されたオブジェクトを返す。

指定イニシャライザ

唯一でなければならず、しかも retain されてゐるオブジェクトを返す。取得した側で責任を持ち release する必要がある。

戻り値の規約

これらで取得する場合は、簡易コンストラクタと異なり、retain されてゐるので、オブジェクトが不用になつたならば、プログラマは release せねばならない。しかしそれ以外の手段(メソッド)で取得できるオブジェクトは autorelease されてゐる。この點に注意されたい。

NSObject クラス

Cocoa における Root class の一つ。實は NSObject のメソッドは NSObject Protocol と NSObject Class のメソッドとに分類できる。

註:Cocoa における Root class は NSObject Protocol を適用する事になる。NSObject Protocol には基本的なメソッドが全て列擧されてゐるから。NSProxy 等。

プロトコル(protocol)

Ruby における module みたいな奴。任意のクラスに幾らでも適用できる。Ruby module が實裝ならば、Obj-C Protocol は宣言に過ぎない。手法が明示的なる物と暗默なる物の二種類ある。

カテゴリ(category)

カテゴリは定義濟のクラスを擴張できる、Objective-C でも一・二を爭ふ邪惡で、そして便利な手段である。譬へば今 NSString に base64 encoding のメソッドをつけ加へてみたいと思ふならば、カテゴリを用ゐることで實現できる。

サブクラス(subclass)

プロパティ(property)

二三の特異な型

NSRange

配列なんかで用ゐる。NSMakeRange で生成できる。

NSSize

NSView 及びそのサブクラスでよく使ふことになる。NSMakeSize

Cocoa との關聯

附録:Objective-C

ディレクティブ(directive)

Objective-C におけるコンパイラ及びプリプロセッサへの命令について。C 標準は勿論のこと、幾らかの擴張がある。それが以下である。

コンパイラのディレクティブ

#import は #include に同じだが、一度しか讀み込まない點が異なる。// は行末迄コメントと解する。

プリプロセッサのディレクティブ

互換性確保の爲に @ で書き始めると謂ふのは、@interface の紹介をした際に書いた。今クラス(そしてそのカテゴリ、プロトコル)を宣言する手段をみれば、

があつて、必ず@end で宣言を閉ぢる。そのインスタンス變數の可視性は次の宣言で示す。

初期設定は@protectedである。例外処理は、

@finally が強制實行部位で、あとはお馴染みか。更に特定の目的が爲、次が用意される。

一往説明が必要なのは @"string" であらう(其れ以外は取り急ぎ必要がないから述べない)。@"string" は quoted な部位を NSString class のレシーバとして處理する構造である。@"abc" と書けば、abc なる文字を保持した NSString class のインスタンスが const として生成される。しかも(同じ stack であればだと記憶するが)@"string" を同メソッド内で何度呼びだしても、同じインスタンスを返してくれる。

その他のディレクティブ

言語仕樣に明るいわけではないが、譬へば NSFastEnumeration Protocol の登場以降(Mac OS X 10.5以降)では、コンパイラは C 標準にない for 文をサポートしれくれる。これもディレクティブである。たまに C 標準ではない物があるとすれば、現在のプログラミングでは一般的な表記を、實用に利する爲に取り入れた表記群であらう。

NSZone と malloc

Mac OS X のメモリ確保方法について。malloc_zone_malloc とかの話。malloc.h みて下さい。

Xcode でのビルド

Xcode は Apple による工夫によつて擧動に「癖」がある。

對象とする Mac OS X の System [Active SDK]

SDK を意識することは結構重要で、API の統廢合は結構よくある。最新の Document をみるか、API のヘッダを讀めば書いてある。LEGASY とある場合は、なるべく遣はない方がよく、新機能新API らしい物は當然互換性の障碍となるから注意である。

ビルド構成

恐らく debug になつてゐるので、「出荷」するときは release にするやうに。ビルド構成は、ビルド時に指定するコンパイラオプション等を保存した物で、任意に切替ることができる。

ターゲット(target)

作る實行ファイルのこと。ビルド前は存在しないから赤い文字で表記される。

リンカ(linker)

ヘッダファイル

デバッガ(debugger)

<デバッガの遣ひ方とか mark の仕方を書きたいのだけれど?>

pch ファイルとプリコンパイル

Cocoa Application では precompile と呼ばれる工程がある。pch ファイルは、C++ でもお馴染みかもしれないが、Precompiled Header の事である。precompile とは文字通り compile の前段階のことで、簡單に謂ふと、キャッシュを用意する事で Cocoa Application のビルド時間が短縮できる。Xcode でこれを編輯することは先づないので、飾り程度に認識しておくとよい。

ただこのキャッシュは 30MB 程度あつて輕くない。10.4 以前なら /Library/Caches/Xcode に、10.5 以降ならば /private/var/folders 下にある -Caches-/com.apple.Xcode.501 に纏まつてある。たくさん Cocoa Application を作つてゐるとこのサイズは途轍もない物になるので、不安になればたまに削除すると宜しい。尚 /private/var/folders 以下は、人によりフォルダが異なるし、501 は UID なので、若し UID が 502 ならば com.apple.Xcode.502 になる場合もあるかもしれない。

實行環境のはなし:Architecture について(32-64bit/PPC, Intel)

VMX(AltiVec) と SSE

C 言語との關聯

const 及び static

@"string" でわかるように、const は使用可能。static は singleton で用ゐる。

インスタンス變數の扱ひ

インスタンス變數は C での構造體のメンバの樣に宣言運用できる。例としてあげれば、@interface 中に int nums[10]; とできる。

メソッドの靜的呼出

メソッドを呼出す行爲は、レシーバの情報から函數ポインタを取出し、それを呼出してゐるに過ぎない。今 <objc/objc-class.h> を import した上で、

id obj = [self getObject];
Method method;
Class class = [self class];
SEL name = @selector(myMethod:);
method = class_getInstanceMethod(class, name);
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5//	OBJC2 UNAVAILABLE
method->method_imp(self, name, obj);
#else
method_getImplementation(method)(self, name, obj);
#endif

とすれば、これは [self myMethod:obj]; と同等である。ここで #if を用ゐるのは、Method のメンバにアクセスできるのは、32 bit 環境且つ Mac OS X 10.4 以前のみだから(正確には Objective-C 2.0 で削除された仕樣であるから)。尚、メソッドを上書きしてゐなければ、self とは別のインスタンス等でも函數ポインタは同一である。若し同一かどうか不安であれば、NSLog(@"%p", method->method_imp); として確かめてみればよい。

註:譬へば method を NSValue のインスタンスに格納して後々利用しようと思ふならば、name が欲しい事もある。その時は、method->method_name 或いは method_getName(method) とすればよい。

參考等

Cocoa

Xcode(舊Project Builder)

Mac OS X における標準的開發環境が Xcode とそのパッケージである。

Xib (Nib) ファイルと Interface Builder

Cocoa アプリケーションでは、GUI 部品(及び Controller Object)をシリアライズした Nib ファイルを讀み込むことで、GUI 生成に關するコードを必要としない開發を實現してゐる。またそれに關する Controller Object を含めることで、GUI 部品からのイベントやアクションへの對處が可能となる。

これらのファイルは、任意の瞬間に、任意の方法で讀み込むことができる。

讀み込まれた Nib ファイルにおいては、保存されたオブジェクトがインスタンス化され、インスタンス化後に NSNibAwaking Protocol の -(void)awakeFromNib が呼ばれる。

NSMainNibFile

Project 中の info.plist の NSMainNibFile、或いは Xcode でターゲットを選択し『情報』ウインドウを開き『プロパティ』タブの『主要Nibファイル』、として指定されてゐるファイル名が、Cocoa アプリケーション起動時に必ず讀み込まれる Nib ファイルである。たとへば Menu Bar に表示される Main menu は主要Nibファイル中でシリアライズされてゐる。

アウトレット(Outlet)とアクション(Action)

Outlet はインスタンス、Action はインスタンスのメソッド。

註:IBOutlet 及び IBAction は C のマクロである。IBOutlet はコンパイル時に無視され、IBAction は void * を表す。

コントローラオブジェクト(Controller object)

Interface Builder の Library に Object と呼ばれる部品があるから、それをドロップすると、立方形のインスタンスが追加される。これが尤も標準的なコントローラの追加方法である。コントローラの役目はいろいろあるが、譬へば GUI 部品へのアクションは、大抵の場合、かうして追加したコントローラに送信することになる。

例:

  1. Xcode で新規プロジェクトを選擇し、適當な名前の Cocoa Application Project を作る。
  2. 次に新規ファイルを選び、ヘッダを含めて AppController クラスを追加して欲しい。AppController の superclass は NSObect でよい。
  3. AppController.h を編輯し、AppController クラスへ -(IBAction)myMessage:(id)sender; を追加する。
  4. AppController.m の AppController クラスには -(IBAction)myMessage:(id)sender{NSLog(@"HELLO WORLD");} と追加する。
  5. MainMenu.xib を開く(恐らくテンプレート通りならこのファイル名である)。すると、File's Owner・First Responder 等と表示された Window と、別の何もない Window が表示される。
  6. Library の Buttons から、Gradient Button を選び、何もない Window にドラッグして乗せる。これで保存すれば、ボタンが追加されてゐる。
  7. Library の Object & Controller から、Object を選び追加する。今度は何もなかつた Window ではない方へ追加する。
  8. 次に初期設定では NSObject の インスタンスであるから、Class Identify の Class を AppController にする。
  9. Gradient Button の Sent Actions の selector に myMessage: を設定する。勿論ターゲットは AppController。Control-Key を押しながら、クリックしてみると・・・?

Interface Builder の遣ひ方は言葉では表現しづらい。一往全て終了したならば、「ビルドと実行」を選び、起動させる。Xcode の「実行 > コンソール」からコンソールを開き、表示されたウインドウのボタンをクリックするとメッセージが表示される筈である。このコンソールには、NSLog の出力の他にエラーメッセージ等も表示されるから、出力には常に注意を拂ふこと。

參考:

基本的なことが書いてある。『Cocoa Fundamentals Guide > オブジェクトとの通信 > ターゲットとアクションの設定』をみること。

註:Cocoa Fundamentals Guide にもあるが、コードでアクションとターゲットを設定することもできる。 NSMainNibFile や Nib ファイルについて上で書いたように、

//   AppController.h
@interface AppController : NSObject
{
      IBOutlet NSButton *button;

//   AppController.m
-(void)awakeFromNib{
      [button setTarget:self];
      [button setAction:@selector(myMessage:)];
}

と書き加へ、定義した outlet が機能するようにボタンへ接續しておけばよい。outlet の接續を行ふことで、 GUI 部品のインスタンスをコントローラ上で取得できるようになる。

課題:『參考』『註』を見ながら、ウィンドウに先程のボタンを無効にするボタンを新たに追加すること。新たなアクションメソッドを必要とする筈である。尚、NSButton には、superclass の NSControl において -setEnabled:(BOOL)flag が定義されてゐる。・・・・課題風にするなら、獨立したページでチュートリアル式にした方が宜しいかもしれない。

File's Owner

Nib ファイルにはその所有者である File's Owner が必ず設定される。それは、

等である。

First Responder

標準でかなり多くのアクションが Main menu から設定されてゐるが、これら全ては最終的に他のオブジェクトへの呼び出しとなる。その仕組みは responder chain と呼ばれる。

バインディング(Binding)

通知(Notification)

Foundation Framework

AppKit Framework

Application Kit (AppKit) には、さまざまな御約束がある。ある程度馴れてくると、ヘッダをみて、通知や委讓がないか確かめたり、クラスの使ひ方がわかるようになる。

CoreData Framework

二三の重要なプロトコル

NSObject Protocol

NSKeyValueCoding Protocol と NSKeyValueObserving Protocol

NSFastEnumeration Protocol

NSCoding Protocol

NSCopying Protocol と NSMutableCopying Protocol

ローカライズ(Localization)

ユーザ設定

附録:Cocoa

API はよく遣ふ物を特に説明する。ただし Core Data については割愛する。

はじめての Programing

Foundation Framework API

NSObject

NSString, NSMutableIString

恐らく尤も頻繁に作られるクラス。

NSData, NSMutableIData

NSDate

NSNumber, NSValue, NSNull

NSDictionary や NSArray に int や nil や 構造體等を納めたい場合にはこれらを用ゐる。NSValue でラップできる物については @encode() 參照。

NSArray, NSMutableArray

NSDictionary, NSMutableDictionary

NSIndexSet, NSMutableIndexSet

NSNotification, NSNotificationCenter

Application Kit Framework API

NSButton

NSTableView, NSArrayController

dataSource と delegate をうまく遣ひこなすこと。

NSOutlineView, NSTreeController

NSTableView 同樣。

NSView, NSViewController

カスタムビューに何か御用ですか?

NSWindow, NSWindowController

key-window と main-window がある。key-window とは、Mac OS X において、唯一キーボードからの入力を受け付ける window。通常 NSWindowController のサブクラスを File's owner として nib ファイルを讀み込み NSWindow を生成することになるが、NSBundle で讀み込み生成してもよい。

NSWindow *w = [myView window]; BOOL ended = [w makeFirstResponder:w];

NSDocument, NSDocumentController

Document-based Application で大活躍。[NSDocumentController sharedDocumentController];

NSApplication

[NSApplication sharedApplication];

參考等

Apple Developer

Xcode の Install と Download

SDKs

分散コンパイル

Document

Open Source

舊版

言語仕樣

要約として次に用意されてゐる。構文もまた參照せよ。

Cocoa とは何か

Cocoa とは、Foudation Frameworks、CoreData Frameworks、AppKit Frameworks により構成される Objective-C の API 群である。

Foudation とは

Foudation は、そのまま「基層」の意である。化粧をする貴方には下地(ファンデ)でおなじみ。Cocoa で尤も酷使される可哀想なやつ。一方で、これの扱ひになれれば Cocoa API はグつとわかりやすいものになる。

抽象的で申し訣ないが、要するには Cocoa の頻出データ型を定め頻出する機能を纏めたやつである。MVC でいへば Model の提供が主で Controller の技術的補助(オブザーバなど)、View に渡すデータなどの役割を擔ふ健氣なやつ。

AppKit とは

AppKit は、ApplicationKit の略である。Kit の接尾辭は Apple では擴張的であれど基本的な API 群につけるらしく、たとへば Safari の KHTML エンジンは WebKit Frameworks で實裝される。Cocoa にラップされた QuickTime API は QTKit である。

感覺を摑むためにも、まづは手元にある Interface Builder を起動させてみて欲しい。起動せば何か作るかと聞いてくるから、Cocoa > Window を選ぶ。Untitled とある畫面にはタブがあり、Instances といふタブが選擇されてゐるはづである。 Cocoa > Window の nib テンプレートには File's Owner、First Responder、Window とある訣だが、Window のアイコンをダブルクリックして欲しい。 君の目の前には眞つ白な「ウインドウ」が現れるだらう。多分表示されてゐると思ふけれど、パレットが無ければメニューから「Tools > Palettes > Show Palettes ⌘/」を選びたまへ。次にこれもおそらく表示されてると思ふけど、パレットにカラフルなイラストで彩られた上段のタブなければ、右上のボタンで表示するやうに。

さあ簡單に説明しよう。これが Cocoa AppKit のインスタンス君たちである。ツベコベいはず、Controls、Text、Data、Containers などの名前付きのタブから部品をマウスで選び、先程私がダブルクリックしろと言ひ散らして君が放つたらかしにしてる「ウインドウ」にドラッグドロップせよ。 あないみじ。何か表示されるね? ああ、されないなら君の Mac OS X Developer Tools は缺陷品だから、抗議の電話をしたまへ。

これが "インスタンス" だ。君がこれから作るアプリケーションはこの Interface Builder で概觀をデザインすることになる。

なほこの インスタンス 豫定部品君たちは Cocoa の高度な抽象化により、君がコードで宣言しなくても Mac OS X によつて勝手に初期化されて表示されることになる。君はではこれの値を變へるにはどうすれば、と思ふだらうから簡單にいふと、委讓關係を設定するか Binding を利用するかになる。恐ろしいことにこれも全て Interface Builder で且つグラフィカルに設定できてしまふ。 先程ウインドウに君はインスタンスを載せた。ボタンやらコンテナやらである。control キーを押し乍らそのインスタンス部品をクリックしてマウスを動かしてみれ呉れ。何か線がニョロニョロ出てくるだらう? これが委讓關係を設定する一つの手段である。細かい事は割愛しようと思ふが、便利でわかりやすいけどわかりにくい構造とならしめてゐる Interface Builder の一端が垣間みれたのではないかな。

すでに他のオブジェクト指向を味はつた貴方に説明するなら、これは Key-Value Coding Protocol(KVC)、Key-Value Observing Protocol(KVO) が活躍することになる。KVC は setter、getter、そして KVO は Observer パターンを實裝するもので、NSObject をルートとするクラスには自動的に備はる機能になつてゐる。protocol は Ruby 的な感じだと規約に當たる物で、かうしませうといふ感じのメソッドの一群。protocol は Objective-C の文法的要素でもある。protocol を實裝したクラスは、protocol の規約に從ひメソッドを定義せねばならない。ただしこれはインスタンスの構造に變更を加へるときのみ必要なだけで、單純に NSObject を繼承したクラスでは KVC の protocol に適合してゐることになる。

先程載せたインスタンスらは nib ファイルに格納し保存される。インスタンスは plist 形式でシリアライズされてをり、Mac OS X のアプリケーションは起動時にこれを參照し復元して GUI 環境を提供してくれる。plist は Foudation の一部のクラスをシリアライズする物で記法は三種類ほど存在する。よく使ふので別項で解説する。nib ファイルはアプリケーションバンドルに必ずあるので、「パッケージの内容を表示」して探してみて欲しい。

MVC でいへば、まさしく View を擔當することは先程の Interface Builder でよくわかつたかと思ふ。Controller もちょっち擔當。

Core Data とは

Core Data は、WebObjects の EOF(Enterprise Objects Framework)の流用である。さつぱりわからん? まあ聞いてくれ。Core ImageだとかCore Audio、Core Video、などのイメージがあるので、私はハードウェア的な實裝なのかとつい勘違ひしたが、これは頗るソフトウェア的である。Core の接頭辭は Carbon API のやうに C で實裝された API をラップする存在に附けられるやうである。先述の Foudation は Carbon API の Core Foundation をラップする。これらは、高速化を圖るための思はれる。

WebObjects はマイナーの嫌ひがあるので説明せば、Mac OS X に無料でバンドルされる Java Servlet の類ひである(なほ元々は純粹なobjcだつたがversion.5よりJavaになつた)。EOF は WebObjects の賣りのひとつで、 サーバ毎に Adaptor を巧みに遣ひわけ猶且つ SQL をデヴエロツパが書く事無くして DataBase を操作する代物であつた。

Core Data は、主に書類を扱ふ際に威力を發揮する。EOF との違ひは、EOF は Java Servlet といふ用途に沿ふ實裝だが、Core Data はデスクトップアプリケーションの爲の API であるといふことである。そこらへんのことは Apple の Core Data の解説に詳しい。

總括

長くなつたけど、序論である。AppKit に項目を割いたのは Cocoa GUI に於いてとても重要であるからである。

また、下記リファレンスの URI に於いて CoreData を除き「ObjC_classic」とあるのは何故かと思はれるかも知れないので付け足して置くと、Foundation と AppKit は OPENSTEP 時代からの遺産であつて、Core Data は Mac OS X Tiger(v.10.4) より導入されたに過ぎない。 ゆゑにクラシックなのである。

API リファレンス(見出し)

參考

Foudation Frameworks

Foudation Frameworks は Carbon の完全なラッパーとなつて居る。幾つか憶えるべき最低限のものを擧げてみれば、それは NSString、NSArray、NSDictionary などのクラスである。まづ、基本的なクラスを紹介する。

NSObject・・・オブジェクトの生成

NSObject はルートクラスであり、次のプロトコルに "接續" する(Adopted Protocol)。

これらのプロトコルで實裝されるのはインスタンスメソッドのみとなる。Cocoa では次のステップを踏みインスタンスを生成する。

NSObject *obj = [NSObject alloc];
[obj init];
[obj autorelease];

インスタンス生成(甲):

alloc はデザインパターンの Factory にあたり、Objective-C ではこのクラスメソッドがメモリ確保を行ふ。絶對に子クラスで上書きしてはならない。なほ alloc は NSObject に實裝されてゐる。これを「割り當て」と呼ぶ。他の言語のやうに new Class といふ記法はないが、new メソッドが存在する(後述)

後述の NSArray や NSString といつたクラスのクラスメソッドには次の物がある。

+ array
+ arrayWithArray
+ string
+ stringWithCString:encoding:
+ allocWithZone
+ new

array*** とあるのは NSArray の Factory であり、string*** とあるのは NSString の Factory にあたる。Cocoa の Factory は戻り値として初期化する前のインスタンスを返す。なほ Objective-C では + を伴ふメソッド定義がクラスメソッドを示す。

割り當てられた領域は NSZone クラスのインスタンスとして(zone メソッドにより)取得することができ、allocWithZone で生成すれば同じ領域を使用できる。また、參照カウント及びインスタンス變數の初期化を行ふ。ここに於いて isa インスタンス變數の決定といふ重大な過程を經過する。

インスタンス生成(乙):

init は初期化メソッドであり、インスタンスメソッドである。子クラスで繼承できるが、親クラスのインスタンスメソッドを實行させること。NSObject に實裝。

- (id)initWithArray:(NSArray *)array
- (id)initWithTimeInterval:(NSTimeInterval)secsToBeAdded sinceDate:(NSDate *)anotherDate
- (id)initWithContentRect:(NSRect)contentRect styleMask:(unsigned int)aStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag
- (id)initWithFrame:(NSRect)frameRect

これも同樣に init*** といふ命名規則を持つ。これは NSSet、NSDate、以降はAppKit だが NSWindow、NSControl(及びNSView) などのメソッドである。

似たやうなメソッドとしてinitializeがあるが、こちらは「クラス」の初期化を擔ふ。一度しか呼ばれない(後述)。なほ初期化した自身を返すのだが、 id 型を返すとあるのはこれを不特定の何か程度に認識して於いてほしい。C の爲に存在し、Objective-C では id 型がオブジェクトを指す。

インスタンス生成(丙):

autorelease は自動で release する、すなはちメモリ解放の爲の手續きである。最近の言語では garbage collection は最早定番とも言へるがこれも似た手段である。解放プールに入れると表現されるが、それはアプリケーション起動時に NSApplication が NSAutoreleasePool クラスのインスタンスを作り、これに叩き込んで監視するからである。

- autorelease
- release
- retain
- retainCount

NSObject Protocol によつてこれらのインスタンスメソッドが定義される。autorelease は明示的に release をするのと變はらぬ效果を與へる。retain は參照カウンタを増大させ release は參照カウンタを減少させるものだが、NSArray といつたコレクションクラスに插入すると自動的に retain が呼ばれ參照カウンタが増える仕組みになつて居る。不要になれば release か autorelease を呼ばねばならない。

正確な意味での garbage collection は Objective-C 2.0 への擴張で組み込まれ Leopard より實裝された。保守的(conservative)な GC である。

インスタンス生成(丁):

他にインスタンス生成に於いて俯瞰せしめた際に見渡せることを書連ねる。Cocoa では isa インスタンス變數を組み込むことでクラスを識別する。かういつたクラスに關する處理で特殊なものがあるから紹介する。

### NSObject: Adopted Protocol
## NSObject Protocol
#	Identifying and Comparing Objects
- isEqual
- hash
- self
#	Describing Objects
- description
#	Sending Messages
- performSelector
#	Determining Allocation Zones
- zone
#	Identifying Proxies
- isProxy

### NSObject Class: Tasks
#	Initializing a Class
+ initialize
+ load
#	Creating, Copying, and Deallocating Objects
+ new
- dealloc
- finalize

### NSString Class: Tasks
- hash
- isEqualToString

あるプロセスに於いて NSMutableString クラス(NSMutableString > NSString > NSObject)が始めて呼びだされたとして、その時に NSMutableString のクラスメソッドたる initialize が自動的に呼び出される。親クラスたる NSString クラスの initialize が呼び出されてゐない場合も同樣である。また、load クラスメソッドもクラスがプログラムに讀み込まれたことを告げるために initialize を呼ぶ前に呼び出される。すなはち次の順となる。

[NSObject load];
[NSObject initialize];
[NSString load];
[NSString initialize];
[NSMutableString load];
[NSMutableString initialize];

new クラスメソッドは次の式と等價である

[NSObject new];

# Pattern1
NSObject *obj = [[NSObject alloc] init];

# Pattern2
NSObject *obj = [[NSObject alloc] init];

ただし、new に渡された引數は init にも渡されることになり、alloc と異なり子クラスで上書きしても構はない。

dealloc はメモリ解放を行ひ、release により呼び出される。明示的に dealloc を呼ぶ事は無い。獨自のメモリ解放機構を備へるなど子クラスで再定義できる。

finalize は dealloc に代はり呼び出される。GC が有效なとき、autorelease を呼んだときなど(よくわからんから調査中)。

description 則ち「説明」とあるけど、これは NSString にインスタンスを變換しこれを返す。所謂「toString」「to_s」 などのメソッドと考へて欲しい。isEqual は何が「イコールか?」と云ふとインスタンスの hash メソッドを用ゐて比較した眞僞値を返す。たとへば、NSString クラスでは hash メソッドが再定義され、同時に isEqualToString が追加された。isEqualToArray、isEqualToDate、isEqualToSet など似たメソッドは澤山ある。self はインスタンス自身を返すメソッド。

zone は先述の NSZone を作つて返すメソッド。これは allocWithZone、copyWithZone といつたやうなクラスメソッドなどの引數となる。

performSelector は SEL、IMP、Methodの三つの型を理解する爲に擧げた。一部の例が Ruby で申し訣ないが、次のやうな物である

  • SEL型:セレクタ。C の構造體のポインタ型(Opaque、實態はchar型)。Ruby だと Symbol クラス。
  • IMP型:メソッドの實裝。C の函數ポインタ。Ruby だと Proc クラスなどか。
  • Method型:メソッド。C の構造體で、SEL型・IMP型・char型を格納する。
### objc-class.h
typedef struct objc_method *Method;
struct objc_method {
    SEL method_name;
    char *method_types;
    IMP method_imp;
};
### objc.h
typedef struct objc_selector *SEL;
typedef id (*IMP)(id, SEL, ...);

### performSelector は次のやうに使ふ(self メソッドを呼ぶ)
SEL *aSelector = @selector(:self); # @selector は ObjC の言語構造である
				# なほこれらの@で始まるこれらの文字をコンパイラへの「ディレクティブ」と呼び、他にも幾つかある。
SEL *aSelector = NSSelectorFromString(@"self"); # この定義濟函數でNSString から SEL に變換できる。
				# 同樣に@"string" はディレクティブであり、呼出したモヂュール内部での NSString のオブジェクト定數となる。
[obj performSelector: aSelector]; # 送信先からの戻り値を返す。id 型なので何でもアリ。

NSString *method = NSStringFromSelector(aSelector); # この定義濟函數で SEL から NSString に變換できる

isProxy が NSObject Protocol に態〻定義されてゐるのは、NSProxy クラスがルートクラスだからである。NSProxy は NSObject Protocol を實裝するけれども、他のクラスと異なり NSObject を繼承しない。クラスとプロトコルの違ひを強調する爲に項を割いた。

confer.參照セヨ

Foundation Collections Types

Cocoa では次のコレクションが用意される。繼承關係も示した

NSArray は配列、NSDictionary は辭書(ハッシュ)、NSSet は集合(聚合、重複を許さぬ配列)です。このクラスに格納したオブジェクトは變更することができない(Immutable)。變更すること(Mutable)を望む場合は次のクラスを使用する。

またコレクションは次のプロトコルを實裝する。

NSFastEnumeration は Objective-C 2.0 より實裝された高速列擧(Leopard 以降)のためのもので次の表記が可能になる。

for(id objectItem in array){
....
}

NSCopying、NSMutableCopying は複製するためのプロトコル。NSObject に複製用メソッドは定義されてゐるものの、NSObject はこのプロトコルに關しては實裝してゐない。

### NSObject Class: Tasks
- copy
+ copyWithZone
- mutableCopy
+ mutableCopyWithZone

### NSArray, NSDictionary, NSSet: Adopted Protocol
## NSCopying Protocol
- copyWithZone
## NSMutableCopying Protocol
- mutableCopyWithZone

confer.參照セヨ

Foundation Primitive / Numerical Types

一方で次のやうなデータ型的な物がある。Primitive とあるやうに基本である Foundation の更に基本構成員たちである。

confer.參照セヨ

Foundation Data Types

更に次のやうな型が定義される。これは C の構造體といふ位置づけになる。

NSRange は特に Foundation に於いて頻出である。これら構造體は CGFloat、NSUInteger などの型を格納する。そんなにややこしいものでもないので「Foundation Data Types Reference」及びヘッダファイルより拔萃。

typedef struct _NSPoint {
   CGFloat x;
   CGFloat y;
} NSPoint;
typedef struct _NSRect {
   NSPoint origin;
   NSSize size;
} NSRect;
typedef struct _NSSize {
   CGFloat width;
   CGFloat height;
} NSSize;
typedef struct _NSRange {
   NSUInteger location;
   NSUInteger length;
} NSRange;

#if __LP64__
typedef long NSInteger;
typedef unsigned long NSUInteger;
#else
typedef int NSInteger;
typedef unsigned int NSUInteger;
endif

NSUInteger は 64bit な Mac と 32bit な Mac に於いての工夫を施すために定義された型となる(註:つまりvoid *、ポインタと同じ大きさ)。

//CGBase.h
typedef float CGFloat;// 32-bit
typedef double CGFloat;// 64-bit

CGFloat 型は「CGGeometry Reference(CGBase.h)」に説明があるけれども、要するにfloat(double)型である。これらを列擧した理由は NSValue がサポートする物だからに他ならない。NSValue がサポートできる型の値は KVC の自動ラッピング機構を利用できる。

また次の定義濟函數で各々の型を作ることができる。

NSMakePoint(x, y)
NSMakeRect(origin,size)
NSMakeSize(width, height)
NSMakeRange(location, length)

confer.參照セヨ

参考


トップ   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS