2012年10月11日木曜日

GCは陳腐化?

ARC:ガベージコレクションは速度の問題で、Xcode4.2以降ではサポートされなくなった。その代わりに出てきたのがARCで、これはいままで手動で行ってきた参照カウンタの管理を自動化する。(http://d.hatena.ne.jp/watarijin/20120703から引用)

declared property 実践

・アクセサの命名
@property (getter=isEnabled, setter=makeEnable:) BOOL enabled;

setter名はコロン(:)を忘れずに。

・unwritable(と勝手に名付けた)
@property (readonly) NSString* firstName; 

setterを作らないので呼べません。

・書き込み可能なオブジェクトの保持(ガベージコレクションの有無で変わる)
GC無効の場合、オブジェクトのオーナーシップをどうすべきか、気にしなくてはいけない。retainを呼んでそのオブジェクトを保持するか、または単に参照を持つだけか。copyは指定されたオブジェクトをコピーして保持すると。

//GCなし
@property (retain) NSString* title;
@property (assign) id delegate;

@property (copy) NSString* value;


ガベージコレクション無効の場合はいずれかの指定子を宣言しないとけないと。

ガベージコレクション有効な場合、無指定ではassignとなる。assignかcopyかは明示しておいたほうが無難と。

declared property 小話

ドット構文とメソッド呼び出しの等価を考えた時、
・プロパティ名からメソッド名への変換規則は、キー値コーディングのものと同じになる。
→キー値コーディングが分かるまではおいておく。

・メソッドが本当に実装されているかどうかのチェックは、実行時に行うというのが原則
・id型クラスのメソッドは宣言しなくともコンパイルは通ってしまう。
・翻って、ドット演算子で記述するとチェックが入る。静的な型チェックが入り、プログラムミスが減ると。
 その例示は以下。インスタンス変数nameはプロパティ宣言がなされていない

id person = [[Person alloc] init];

// id型のプロパティにアクセスする
// エラーになる
NSString* name = person.name;

// 存在しないプロパティにアクセスする
// エラーになる
NSString* lastName = ((Person*)person).lastName;

 アクセサ記述は省略できたが、そのかわり増える記述もあるのだ(上のキャストがその例)。

decrared propertyの雛形

理論より実践で。あるサイトからの雛形としては 
@interface MyObject : NSObject
{
     // プロパティに対応するインスタンス変数
   NSString* name;
}
@property (retain) NSString* name;
@end
アクセサを設定したいプロパティ名(型)を宣言。典型的にはインスタンス変数に対応させるが、(例では同じであるが)名前は異なっても良いとのこと。


 一方、The Objective-C Programming Languageではsimple〜として
@interface MyClass : NSObject
@property float value;
@end
とある。

実装部ではそれぞれ、
@implementation MyObject
@synthesize name//もし異なっていれば ( = instance変数名);
@end

@interface MyClass : NSObject
@property(copy, readwrite) NSString *value;
@end
@implementation MyClass
@synthesize value;
@end
となる。後者はinterfaceも提示。
setter、getterともに各自で実装しても良い。規定外名ならattributeに名前を設定する。
実行時に動的に確認できればよいならば、実装部で@propertyの代わりに
@dynamic name;
を書いておけば良いと。

インスタンス変数の宣言についての説明が不足していた。
The Objective-C Programming Language(2011/10/12版)にしっかり書いています。
項目Declared Properties-小項目Runtime Differenceに、
There is one key difference: the modern runtime supports instance variable synthesis whereas the legacy runtime does not.
とある。Objective-C Runtime Programming Guideでは、runtimeのバージョンは2つあり(modernとlegacy)、modernであるruntimeはObjective-C 2.0ととも導入された。それら差の特徴が以下(最後の追加的な記述)。

The most notable new feature is that instance variables in the modern runtime are “non-fragile”:

・In the legacy runtime, if you change the layout of instance variables in a class, you must recompile classes that inherit from it.
・In the modern runtime, if you change the layout of instance variables in a class, you do not have to recompile classes that inherit from it.

In addition, the modern runtime supports instance variable synthesis for declared properties (see Declared Properties in The Objective-C Programming Language ).
ようするにlegacyでは、継承する側のクラスは、親クラスのインスタンス変数の順序が変わった場合、リコンパイルが必要となるが、modernではその必要がない。またdeclared propertyの合成もサポートされている。

ガベージコレクションの基礎

wikipediaより:ほぼまるまるコピーになってしまった。
ガベージコレクション(garbage collection; GC)とは、プログラムが動的に確保したメモリ領域のうち、不要になった領域を自動的に解放する機能である。
「コンパクション」とは、:
メモリの断片化を解消する機能と併せてガベージコレクションと呼ぶ場合もあるが、厳密にはそのような機能はコンパクションと呼び、区別される。

動作方法は:(wikiの要約)
(要約)従来のメモリ管理では、メモリが必要となる期間を考え、必要となった時点でメモリを確保、不要となった時点で開放するコードを記述していた。
GCを使用すると(メモリを確保するコードは明示的に記述するが)、メモリの開放については明示的に記述する必要がなく、ガベージコレクタが不要と判断した時に、自動的にメモリを開放する。確保したメモリが不要かどうかは、プログラムが今後そのメモリにアクセスするかどうかで決まり、スタックや変数テーブルなどから参照をたどってメモリに到達可能かどうかによって判断される。
ガベージコレクションの機能は、初めから言語処理系に組み込まれている場合や、後付けのライブラリなどによって提供される。
特徴 :
ガベージコレクションはプログラム作成者が明示的にメモリの確保・解放を行う必要が無いため、以下に示すメモリ管理に関連する陥りやすいバグを回避することができる。

メモリリークの回避
    ガベージコレクションは、オブジェクト(データを格納したメモリ領域)とそれを指し示すポインタを管理するため、オブジェクトは存在しているがそれを指すポインタが無い状態を回避することができる。
オブジェクトの二重解放の回避
    いったん解放したオブジェクトをさらに解放することを防ぐ。
無効なポインタの回避
    たとえば、サブルーチンで確保したオブジェクトへのポインタを呼び出し元に戻す場合に、確保したオブジェクトがローカル変数のため、サブルーチンを抜けるとオブジェクトが破棄されることがある。呼び出し元に戻されたポインタにはあるアドレスが代入されているが、そのアドレスにはオブジェクトが存在せず、ポインタは無効なメモリアドレスを指している。このような無効なポインタをダングリング・ポインタ(Dangling pointer)といい、ガベージコレクションはこの問題を回避する。

ただしガベージコレクションにおいても、今後使用することのないオブジェクトへのポインタをいつまでも保持しているようなコードでは、いつまでもオブジェクトが解放されず、メモリ不足を起こしてしまう。これは論理的な設計の問題であり、ガベージコレクションを持つ処理系においてもこの種のメモリリークは発生する。

メモリ管理に関するバグを回避する以外に、プログラミングスタイルの選択肢を広げる効果も持つ。型変換などのために一時的なオブジェクトを生成する、マルチスレッドを利用したプログラムでスレッド間でオブジェクトを共有して使用する、といった処理はメモリ確保・解放の処理の記述が煩雑となることが多い。しかし、ガベージコレクションを持つ言語処理系においては煩雑な記述を省略することができ、これらの処理をより自然に記述することができる。

多くの実装では、入れ違いにより誤って到達可能なメモリが不可能と判断されないように、ガベージコレクトが開始されると他の処理を止め、本処理が中断される(Stop-the-world ガベージコレクタ) 。CPUを長時間(数百ミリ秒から数十秒)占有することもある。ガベージコレクションの動作タイミングの予測やCPUの占有時間の事前予測などが困難なことから、デッドラインが決められているリアルタイムシステムに使用することは難しい。リアルタイム性を改善したGCとして、インクリメンタルGCやコンカレントGCがある。

手法:複数の手法がある。

参照カウント
    オブジェクトを参照するポインタの数を数え、参照するポインタの数がゼロになったら解放する方法。循環参照の問題がある。解放が集中したときに、単純な実装だと停止時間が長くなる。

マーク・アンド・スイープ
    オブジェクトから別のオブジェクトへの参照をたどり、到達出来ないオブジェクトを破棄する方法。

コピーGC
    通常使用するメモリ領域と同じ容量のメモリ領域をもうひとつ用意し、ガベージコレクションの際に有効なオブジェクトのみをもう一方のメモリ領域にコピーする方法。メモリ領域をデータ保持に必要な容量の2倍消費すること、コピーの際にオブジェクトのアドレスが変更されることなどの欠点があるが、ガベージコレクションとコンパクションが同時に行える利点がある。

これらのアルゴリズムは複合して使用することもあり、世代別ガベージコレクションではコピーGCとマーク・アンド・スイープの両方のアルゴリズムを使用している。

また、アプリケーション動作への影響の観点から、アプリケーション動作をすべて止めるStop the world方式と、アプリケーション動作と並行して動作するコンカレント方式に分類することができる。

Objective-Cでは:
Objective-Cのガベージコレクションは、保守的であり、コピーは行わず(ゆえにコンパクションも行わない)、マーク・アンド・スイープでコレクションを行い、世代別コレクションをサポートする(http://news.mynavi.jp/column/objc/098/index.htmlより引用)
Objective-Cのガベージコレクションの特徴として、コピーは行わなず、したがってコンパクションも行わない

Declared Propertiesの基礎

Declared Properties:The Objective-C Programming Language(2011-10-12版)

一言で言うと、
a simple way to declare and implement an object’s accessor methods.
プロパティに対するアクセスはアクセサ(setter/getter)で行う。これを用いることはカプセル化を順守することでもある。アクセサメソッドを用いることは充分に有利なことであるが、アクセサメソッドを書くことは退屈である。

などの問題に対し、declared propertyは下記の特徴をもち、これらを解決する。
・アクセサメソッドを明示する
・宣言の際に提示した条件にて、コンパイラが自動的にアクセサを合成(synthesize)する
・プロパティは識別子にて文法的に置き換えられ、スコープも決定する。これにより宣言されていないプロパティも特定することができる。

プロパティの宣言と実装
宣言の仕方は、
@property (attributes) type name;
実例は
@property float value;
で、以下と等価である。
- (float)value;
- (void)setValue:(float)newValue;
アトリビュートの設定も可能(アトリビュートとは何であるかは置いておいて。。)
Writability(readwrite | readonly)
 readonly = setterを作らないと同義。
Setter Semantics(strong | weak | copy | assign | retain)
Atomicity(設定できるのはnonatomicのみ)

詳細はあとで。

※「キー値コーディングは、Mac OS X 10.3(Panther)の時代にCocoaバインディングの一部として追加されたもの」http://news.mynavi.jp/column/objc/104/index.html

2012年10月10日水曜日

Main Nib Fileの意味

application’s Info.plist内に記載されている、
key:Main nib file base name
value:MainMenu
にて設定されるMainMenu.xibはアプリケーションのローンチ時にロードされるxibファイルとなる。

Interface builderで見ると、プレースホルダー(nibファイル内にないが、実態はファイル外に存在するとの意味)と、nib内のオブジェクトがある

プレースホルダにはThe File’s Owner proxy object、The First Responder proxy object、A representation of the singleton instance of NSApplication(Aの形をしたアイコン)がある。

nib内のオブジェクトには[A menu]、[A window]、[An instance of AppDelegate]、[An instance of NSFontManager]などがある。

Target-Actionの基礎

Target-Action: Your First Mac App(2012-2-16版)より

Target-action is a design pattern that enables an object to respond to a user event by sending a message to another object. The other object interprets the message and handles it as an application-specific instruction. For example, in this application a button (the object) tells the controller to send a message to the track (the target), setting the volume to zero (the action).

ターゲットアクションとはデザインパターンである。あるオブジェクトに対するユーザーイベントを他のオブジェクトに送信することで行う。受け取る方のオブジェクトはそのアプリケーション独自の決まりにそってメッセージを解釈しふるまう。たとえば実例ではボタンオブジェクトは、コントローラに対し、トラック(the target)へボリュームを0にせよ(The Action)とのメッセージを送るよう指示する。

Delegationの基礎

Delegation -- Your First Mac App.(2012-02-16版)より
Delegation is a design pattern in which one object sends messages to another object—specified as its delegate—to ask for input or to notify it that an event is occurring. Delegation is often used as an alternative to class inheritance to extend the functionality of reusable objects. For example, before a window changes size, it asks its delegate whether the new size is ok. The delegate replies to the window, telling it that the suggested size is acceptable or suggesting a better size. (For more details on window resizing, see the windowWillResize:toSize: message.)
 デレゲーション(和訳:委任、代理)とは、1つのデザインパターンである。イベントが起こった時にあるオブジェクトが他のオブジェクト(デレゲーションとして)にメッセージを送り、入力やイベントの通知を行う。デレゲーションは、再利用可能なオブジェクトの機能的な拡張を、クラスの継承の代わりに行うときに用いられる方法である。例えば、ウインドウサイズの変更(訳中:というイベント)がおこる前にそのデレゲートに対し新たなサイズの妥当性を問い合わせる。デレゲートはそのウインドウに対し許容範囲であるか、より適当なサイズを答える。

Delegate methods are typically grouped into a protocol. A protocol is basically just a list of methods. The delegate protocol specifies all the messages an object might send to its delegate. If a class conforms to (or adopts ) a protocol, it guarantees that it implements the required methods of a protocol. (Protocols may also include optional methods).

 デレゲートメソッドは典型的にはプロトコルに分類される。プロトコルは基本的には「ただ」のメソッドのリストである。デレゲートプロトコルはあるオブジェクトがそのデレゲートにおくるはずのすべてのメッセージを規定する。あるクラスがプロトコルを承認/採用しているとは、 そのクラスがあるプロトコルの(要求された)メソッドが実装されていることを保証していることを指す。

In this application, the application object tells its delegate that the main startup routines have finished by sending it the applicationDidFinishLaunching: message. The delegate is then able to perform additional tasks if it wants.

実例のアプリケーションではアプリケーションオブジェクトがそのデレゲートに対しメインスタートアップルーチンが終わったことを、applicationDidFinishLaunching:メッセージにて送信する。そしてデレゲートは必要であれば追加的なタスクを実行することができる(プログラマーがコードを追加することで)。

[まとめ]デレゲートとは、
・to ask for input or to notify it that an event is occurring
・an alternative to class inheritance to extend the functionality of reusable objects
・ typically grouped into a protocol

趣旨が変わります。

趣旨が変わります(変えます)。
しばらくプログラミング演習のメモログとなります。