9

ソースがないサードパーティのフレームワークを使用しています(使用する必要があります)。サードパーティのフレームワークは、認証されたクライアント/サーバー接続の作成を処理し、開いているNSStreamのペアを返します。

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

ストリームの廃棄プロセスは、クローズ、スケジュール解除、リリースです。

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

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

4

1 に答える 1

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ます。

于 2012-05-27T18:55:28.433 に答える