2013-08-27 5 views
9

背景。NSObjectのカテゴリは、このカテゴリの.hファイルをインポートしなくても、すべてのNSObjectサブクラスで使用できます。

次の手順を検討してください:

1)Xcodeでは、新たな "シングルビューアプリケーション" を作成します。

2)は、カテゴリNSObjectの+ Extension.hとの.mファイルを作成します。

// .h 
@interface NSObject (Extension) 
- (void)someMethod; 
@end 

// .m 
@implementation NSObject (Extension) 
- (void)someMethod { 
    NSLog(@"someMethod was called"); 
} 
@end 

3)NSObject+Extension.mファイルをメインターゲットに含まれていることを確認してください。 #import "NSObject+Extension.hラインはどこにでもアプリで存在していないことを確認してください

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    [[NSString new] performSelector:@selector(someMethod)]; 

    return YES; 
} 

5):

4)はAppDelegateに次の行を追加します!

6)アプリケーションを実行します。

出力は

2013-08-27 04:12:53.642 Experimental[32263:c07] someMethod was called 

質問

  1. どこでもアプリでこのカテゴリのいずれかの#import何が存在しない場合、私は疑問に思う、それは可能でもあるかです NSStringにはまだNSObject + Extensionがありますか?この振る舞いは私が宣言したカテゴリをのスコープ内でのみ宣言したいので、私が宣言するすべてのObjective-Cカテゴリについて非常に悪いと感じさせます。が宣言されています。たとえば、NSObjectをある種のクラスでのみExtensionで拡張したいのですが、アプリケーション全体ではそうではありません。そうでなければ、そのグローバル空間は "汚染された"ものになります。

  2. この現象を回避する方法はありますか?カテゴリを明示的にインポートするときにのみカテゴリを使用したいと思っています。実行するターゲットにリンクさせるだけではありません。

答えて

14

このカテゴリーの#importがアプリケーション内のどこにも存在しないのでしょうか?NSStringにはNSObject + Extensionがまだありますか?この動作により、私が宣言するカテゴリは、宣言されているスコープ内でのみ使用可能にしたいので、私が宣言するすべてのObjective-Cカテゴリについては非常に悪いと感じさせます。たとえば、NSObjectをExtensionによって拡張するには、あるクラスだけではなく、そのグローバルスペースがそうでなければ「汚染」になるため、アプリケーション全体ではないようにします。

Objective-Cのオブジェクトには名前空間がありません。クラスにメソッドがあると宣言した場合(カテゴリ経由でもプライマリでも@interface)、の場合はすべて、そのクラスのインスタンスにそのメソッドがあります。

Objective-Cが「プライベート」メソッドを扱う方法は、問題のメソッドについて他の人に伝えないことです(これは、これらのメソッドを宣言するファイルではありません。#import)。これは、-Wundeclared-selector(コンパイラが知らないセレクタを使用するかどうか警告します)と組み合わせると、あなたが得ようとしているほどのガードが得られます。

しかし、最終的なバイナリに.mファイルをコンパイルしても、になります。誰もそれについて "知っていなくても"です。

この現象を回避する方法はありますか?カテゴリを明示的にインポートするときにのみカテゴリを動作させたいと思っています。

ええと、-Wundeclared-selectorを使用すると、Xcodeが警告します。

4

ヘッダーを含めると、コンパイラーがそれを知るようになります。それは、xCodeがターゲットに含まれるすべてのファイルをコンパイルするので、それをコンパイルします。実行時にメソッドがそこにあります。したがって、コンパイル時間チェックのためにそれを含めなかったとしても、オブジェクトはそのカテゴリメソッドに応答します。

関連する問題