メソッドの場合:
[NSThread detachNewThreadSelector:@selector(method:) toTarget:self withObject:(id)SELECTOR];
@selectorを渡すにはどうすればよいですか?コンパイルするために(id)にキャストしようとしましたが、実行時にクラッシュします。
具体的には、次のようなメソッドがあります。
+(void)method1:(SEL)selector{
[NSThread detachNewThreadSelector:@selector(method2:) toTarget:self withObject:selector];
}
クラッシュします。スレッドの準備ができたときに新しいスレッドがセレクターを呼び出せるように、クラッシュせずにセレクターを渡すにはどうすればよいですか?
ここでの問題は、セレクターをメソッドに渡すこと自体ではなく、オブジェクトが期待される場所にセレクターを渡すことです。非オブジェクト値をオブジェクトとして渡すには、 NSValue
を使用できます。この場合、NSValueを受け入れ、適切なセレクターを取得するメソッドを作成する必要があります。以下に実装例を示します。
@implementation Thing
- (void)method:(SEL)selector {
// Do something
}
- (void)methodWithSelectorValue:(NSValue *)value {
SEL selector;
// Guard against buffer overflow
if (strcmp([value objCType], @encode(SEL)) == 0) {
[value getValue:&selector];
[self method:selector];
}
}
- (void)otherMethodShownInYourExample {
SEL selector = @selector(something);
NSValue *selectorAsValue = [NSValue valueWithBytes:&selector objCType:@encode(SEL)];
[NSThread detachNewThreadSelector:@selector(methodWithSelectorValue:) toTarget:self withObject:selectorAsValue];
}
@end
NSStringFromSelector()
およびNSSelectorFromString()
関数を使用して、セレクターと文字列オブジェクト間で変換できます。そのため、代わりに文字列オブジェクトを渡すことができます。
あるいは、メソッドを変更したくない場合は、NSInvocation
を作成してメソッド呼び出しの呼び出しを作成し(非オブジェクト引数で呼び出しを設定できるため)、それを呼び出すことができます[NSThread detachNewThreadSelector:@selector(invoke) toTarget:myInvocation withObject:nil];
を行います
NSValueを次のように使用します。
+(void)method1:(SEL)selector {
NSValue *selectorValue = [NSValue value:&selector withObjCType:@encode(SEL)];
[NSThread detachNewThreadSelector:@selector(method2:)
toTarget:self
withObject:selectorValue];
}
NSValueは、任意の非オブジェクト型のオブジェクトラッパーとして意図されています。
参照してください: 引数としてメソッドを渡す
オブジェクトを指定したくない場合は、nilを使用してください。
[NSThread detachNewThreadSelector:@selector(method:) toTarget:self withObject:nil];
オブジェクトをセレクターに渡す必要がある場合は、次のようになります。
ここでは、メソッド「setText」に文字列を渡します。
NSString *string = @"hello world!";
[NSThread detachNewThreadSelector:@selector(setText:) toTarget:self withObject:string];
-(void)setText:(NSString *)string {
[UITextField setText:string];
}