コンパイラフラグ

XCode4でファイル毎のコンパイルフラグを設定するには以下の場所で設定する。

../../../_images/complierFlag.png

実際に使うのは以下の2つくらい。

  • arcをファイル毎にON/OFFする時
“-fobjc-arc” / “-fno-objc-arc”
  • 最適化をファイル毎に変更する時
“-O0”(なし)から”-o3”(速い)、あるいは”-Os”(速くて小さい)。

プロジェクト全体を”-Os”が設定されている時、デバッグがうまく出来ない事がある。 そんな時に、その特定のファイルだけ”-O0”にすると良いかもしれない。

Objective-Cのsingleton

「Objective‐Cフレーズブック」のSingletonの部分の記述が面白い。

p75より

Appleのドキュメントでは、シングルトンを作成する為に、+sharedInstanceメソッドの中で@synchronized(sefl)を使用する事を推奨しています。 そのアプローチは著しく遅く、このセクションで提案したアプローチよりも多くのコードが必要なため、あまりお勧めしません。

との事。

Appleのやり方、「シングルトンインスタンスの作成」 を見ると

static MyGizmoClass *sharedGizmoManager = nil;

+ (MyGizmoClass*)sharedManager
{
    @synchronized(self) {
        if (sharedGizmoManager == nil) {
            [[self alloc] init]; // ここでは代入していない
        }
    }
    return sharedGizmoManager;
}

+ (id)allocWithZone:(NSZone *)zone {
{
    @synchronized(self) {
        if (sharedGizmoManager == nil) {
            sharedGizmoManager = [super allocWithZone:zone];
            return sharedGizmoManager;  // 最初の割り当てで代入し、返す
        }
    }
    return nil; // 以降の割り当てではnilを返すようにする
}
.
.
.

となっており、確かに+ (MyGizmoClass*)sharedManagerで@synchronized(self)を使用している。

一方、「Objective‐Cフレーズブック」のやり方は、

static MyGizmoClass *sharedGizmoManager = nil;

+ (void) initialize
{
    if( [MyGizmoClass class] == self )
    {
        sharedGizmoManager = [self new];
    }
}

+ (MyGizmoClass*)sharedManager
{
    return sharedGizmoManager;
}

+ (id)allocWithZone:(NSZone *)zone {
{
    if( sharedGizmoManager && [MyGizmoClass class] == self )
    {
        [NSException raise:NSGenericException
                    format:@"May not create more than one instance of singleton."];
    }

    return [super allocWithZone:zone];
}
.
.
.

となっており、@synchronizedがなく、全体的にすっきりしたコードだ。

しかし、脚注にGCCのランタイムにはバグがあって「Objective‐Cフレーズブック」のやり方は動作しないような事が書いてある。

結論としては、gccを使う場合はAppleの推奨する方法を使うのが良いとの事だろうか。

メソッド名合成を使ったプログラミング(1)

「メソッド名合成を使ったプログラミング(1)」の続き

メソッド名合成プログラミングその2

Cocoaライブラリの例以外には、Cocoa勉強会 関東57回目で発表した「五年後のControlEnabler」でもメソッド名合成を使ってプログラミングしている。

このControlEnablerでは、target-actionパラダイムを利用して、NSControlのサブクラスの挙動を変更する仕組みです。

target-actionパラダイムでは、変数targetによって示されるオブジェクトへ変数actionによって示されるメソッドを呼出します。

関係は以下の図のように、ボタンからコントローラへの一方通行。

../../../_images/target-action.png

ここで、ControlEnablerを導入しすると、windowのupdateのタイミングでボタンはコントローラのデータを読み取り、ボタンの挙動を変更する。

../../../_images/ControlEnabler.png

target-actionパラダイムでtargetとして指定されたオブジェクトは、actionを実行出来るのだから”おそらく”actionに関する他の事柄も知っているだろう、言う前提の仕組みです。

ここで、コントローラにactionメソッドとして “anAction:”が有るとすると、以下のメソッドを定義する事でbuttonの挙動を変更出来ます。

- (IBAction) anAction:(id)sender;        // action
- (BOOL)     canAnAction:(id)sender;     // actionを呼出すボタンの有効無効を制御
- (NSString*)titleOfAnAction:(id)sender; // actionを呼出すボタンのタイトルを制御

ここで、上記のように”anAction:”を共通の文字列として、can<action名>、titleOf<action名>といったメソッド名を合成して、update毎に呼出してその値をボタン自身に適応する。

ControlEnablerでは、このようなメソッド名合成を使ったプログラミングを使用している。

メソッド名合成プログラミングその3

その他にも状態遷移クラス等の設計等で使えると思うけど、作ってません。

“<状態名>Enter”や”<状態名>Exit”等のメソッド名を合成してデリゲートを呼出せば、switch分が減る。

ヘビーノベル

ライトノベルがあるならヘビーノベルもあるのかもしれない。

大江健三郎がQJをシャウトする、そんなイメージ。