2012-05-24 3 views
9

私はソースを持っていないサードパーティのフレームワークを使用しています(使用する必要があります)。サードパーティのフレームワークは、認証されたクライアント/サーバ接続の作成を処理し、開いているNSStreamのペアを返します。開いているNSStreamに関連付けられているNSRunLoop/NSThreadを調べることはできますか?

ストリームの作成プロセスは、Appleのドキュメントごとに、alloc/init、デリゲートの設定、実行ループのスケジュール、およびopenです。 Appleのドキュメントでは、「ストリームの実行ループを所有しているスレッドとは別のスレッドからスケジュールされたストリームにアクセスしようとしないでください。 https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Streams/Articles/ReadingInputStreams.html#//apple_ref/doc/uid/20002273-1001844

ストリーム処理プロセスは、クローズ、スケジュール解除、解放です。

ストリーム自体を作成する場合は、ストリームがスケジュールされた場所が明確です。サードパーティのフレームワークがストリームを作成する場合、ストリームがスケジュールされた場所がわからないことがあります。

見つかったドキュメントを見ると、開いているNSStreamが関連付けられているNSRunLoopとNSThreadをプログラムで判断する方法はありませんでした。実行時にこの情報を判断する方法はありますか?

+0

エディタがObjective-Cランタイムタグを削除しましたが、質問に対する回答が表示されませんでした。答えがあれば、それはランタイムの質問に非常によく関わっていると私は信じています。したがって、ランタイムタグはそのままの状態にしておいてください。 – xyzzycoder

+1

_answer_が特定のドメインに存在する可能性があるということは、_question_にそのようなタグを付けなければならないという意味ではありません。 ObjCランタイムは、スレッド、ストリーム、および実行ループよりも低いレベル(または少なくとも異なるもの)です。これはフレームワークの概念です。 –

+0

フレームワークに名前を付けることはできますか?あなたはストリームオブジェクトの実際のクラスを知っていますか? 'NSInput' /' OutputStream'またはカスタムサブクラスですか? –

答えて

3

コードはとなり、おそらくとなりますので、注意して使用してください。

私たちは、次のクラス・カテゴリー定義:

@interface TheSpecificNSStreamClass (ProposedCategory) 

@property (nonatomic, strong, readonly) NSArray* associatedRunLoops; 

- (void)myScheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode; 
- (void)myRemoveFromRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode; 

@end 

と実装:

@implementation TheSpecificNSStreamClass (ProposedCategory) 

- (NSArray*)associatedRunLoops 
{ 
    return [NSArray arrayWithArray:objc_getAssociatedObject(self, @"___associatedRunloops")]; 
} 

- (void)myScheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode 
{ 
    NSMutableArray* runloops = objc_getAssociatedObject(self, @"___associatedRunloops"); 

    if(runloops == nil) 
    { 
     runloops = [NSMutableArray array]; 
     objc_setAssociatedObject(obj, @"___associatedRunloops", runloops, OBJC_ASSOCIATION_RETAIN); 
    } 

    [runloops addObject:aRunLoop]; 

    [self myScheduleInRunLoop:aRunLoop forMode:mode]; 
} 

- (void)myRemoveFromRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode 
{ 
    NSMutableArray* runloops = objc_getAssociatedObject(self, @"___associatedRunloops"); 

    [runloops removeObject:aRunLoop]; 

    [self myRemoveFromRunLoop:aRunLoop forMode:mode]; 
} 

@end 

、アプリケーションデリゲートでのいくつかの場所で、私たちは2つのオリジナルのメソッドを交換する方法のスウィズリングを使用実装:

Method origMethod = class_getInstanceMethod([TheSpecificNSStreamClass class], @selector(scheduleInRunLoop:forMode:)); 
Method altMethod = class_getInstanceMethod([TheSpecificNSStreamClass class], @selector(myScheduleInRunLoop:forMode:)); 
if ((origMethod != nil) && (altMethod != nil)) 
{ 
    method_exchangeImplementations(origMethod, altMethod); 
} 

origMethod = class_getInstanceMethod([TheSpecificNSStreamClass class], @selector(removeFromRunLoop:forMode:)); 
altMethod = class_getInstanceMethod([TheSpecificNSStreamClass class], @selector(myRemoveFromRunLoop:forMode:)); 
if ((origMethod != nil) && (altMethod != nil)) 
{ 
    method_exchangeImplementations(origMethod, altMethod); 
} 

結果の配列にはすべて関連するNSRunLoop

+0

これは巧妙なアイデアであり、試してみる価値があります! –

+0

@Leo Natanありがとう。 NSStreamsが作成されると、NSStreamを特定の実行ループ(アソシエーション、スレッド)でスケジュールすることを含む、初期化のための特定のシーケンス(Appleのドキュメントごと)があります。 - scheduleInRunLoop:forMode: Appleのドキュメントでは、「ストリームの実行ループを所有するスレッドとは別のスレッドからスケジュールされたストリームにアクセスしようとしないでください。ですから、私が解決しようとしている課題は、NSStream(またはスレッド/実行ループ)を調べてNSStreamのスケジュール場所を調べるメカニズムがあるかどうかです。 – xyzzycoder

+0

このメソッドを少し後で使用するように私の答えを更新します。 –

関連する問題