私はNSInvocationOperation
は、操作のための自動解放プールを作成するかどうかをテストするための小さなプログラムを書いている:
#import <Foundation/Foundation.h>
@interface MyClass : NSObject
@end
@implementation MyClass
- (void)performSomeTask:(id)data
{
NSString *s = [[[NSString alloc] initWithFormat:@"hey %@", data]
autorelease];
if ([[NSThread currentThread] isMainThread])
NSLog(@"performSomeTask on the main thread!");
else
NSLog(@"performSomeTask NOT on the main thread!");
NSLog(@"-- %@", s);
}
@end
int main(int argc, char *argv[]) {
MyClass *c = [MyClass new];
if (argc == 2 && strcmp(argv[1], "nop") == 0)
[c performSomeTask:@"ho"];
else {
NSInvocationOperation *op = [[NSInvocationOperation alloc]
initWithTarget:c
selector:@selector(performSomeTask:)
object:@"howdy"];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:op];
[op waitUntilFinished];
[op release];
[queue release];
}
[c release];
return 0;
}
それは次のように動作します:「NOP」コマンドラインで渡された場合、それは意志メインスレッド上で、自動解放プールを使用せずに直接-performSomeTask:
を実行してください。結果は次のようになります。
$ ./c nop
*** __NSAutoreleaseNoPool(): Object 0x10010cca0 of class NSCFString autoreleased with no pool in place - just leaking
performSomeTask on the main thread!
-- hey ho
-performSomeTask:
の自動再生文字列はリークを引き起こします。
"nop"を渡さずにプログラムを実行すると、異なるスレッドのNSInvocationOperation
を介して-performSomeTask:
が実行されます。出力結果は次のとおりです。
$ ./c
*** __NSAutoreleaseNoPool(): Object 0x100105ec0 of class NSInvocation autoreleased with no pool in place - just leaking
*** __NSAutoreleaseNoPool(): Object 0x100111300 of class NSCFSet autoreleased with no pool in place - just leaking
*** __NSAutoreleaseNoPool(): Object 0x100111b60 of class NSCFSet autoreleased with no pool in place - just leaking
*** __NSAutoreleaseNoPool(): Object 0x100105660 of class NSCFSet autoreleased with no pool in place - just leaking
performSomeTask NOT on the main thread!
-- hey howdy
私たちが見ることができるように、そこにをリークしているNSInvocation
とNSSet
のインスタンスであるが、-performSomeTask:
で自動解放文字列がをリークされていない、ので、自動解放プールはその呼び出し操作のために作成されました。
私はそれがNSInvocationOperation
(とAppleの枠組み内proballyすべてNSOperation
サブクラス)が並行処理プログラミングガイドでは、カスタムNSOperation
サブクラスのための示唆と同じように、自分自身の自動解放プールを作成することを前提としても安全だと思います。
iOS 3.xでこれをテストしましたか?これは、ここに記載されているGCDの実装の詳細かもしれません:http://stackoverflow.com/questions/4141123/do-you-need-to-create-an-nsautoreleasepool-within-a-block-in-gcd – Danra
@Danra AFAICT NSOperationQueueはGCDを使用しません。また、上記のコードを '[op start]'を介して同期的に実行するように変更すると、文字列が漏れていることを示すメッセージは表示されません。つまり、 'NSInvocationOperation'がオペレーションの自動解放プールを作成します。 –
@Danra私はMac OS 10.6.6でこの動作をテストしました。 –