For the method:
的方法:
[NSThread detachNewThreadSelector:@selector(method:) toTarget:self withObject:(id)SELECTOR];
How do I pass in a @selector? I tried casting it to (id) to make it compile, but it crashes in runtime.
如何传入@selector?我尝试将它强制转换为(id)以使其编译,但它在运行时崩溃。
More specifically, I have a method like this:
更具体地说,我有这样一个方法:
+(void)method1:(SEL)selector{
[NSThread detachNewThreadSelector:@selector(method2:) toTarget:self withObject:selector];
}
It crashes. How do I pass in the selector without crashing, so that the new thread can call the selector when the thread is ready?
它崩溃。如何在不崩溃的情况下传入选择器,以便当线程准备好时,新线程可以调用选择器?
5 个解决方案
#1
67
The problem here isn't passing a selector to a method, per se, but passing a selector where an object is expected. To pass a non-object value as an object, you can use NSValue
. In this case, you'll need to create a method that accepts an NSValue and retrieves the appropriate selector. Here's an example implementation:
这里的问题不是将选择器传递给方法本身,而是将选择器传递给预期的对象。要将非对象值作为对象传递,可以使用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
#2
41
You can convert between selectors and string objects using the NSStringFromSelector()
and NSSelectorFromString()
functions. So you can just pass string objects instead.
您可以使用NSStringFromSelector()和NSSelectorFromString()函数在选择器和字符串对象之间进行转换。所以你可以只传递字符串对象。
Alternately, if you don't want to change your methods, you can create an NSInvocation
to create an invocation for your method call (since it can set up invocations with non-object arguments), and then to call it do [NSThread detachNewThreadSelector:@selector(invoke) toTarget:myInvocation withObject:nil];
或者,如果您不想更改方法,您可以创建一个nsincall来为您的方法调用创建一个调用(因为它可以用非对象参数设置调用),然后调用它do [NSThread detachNewThreadSelector:@selector:@selector(调用)toTarget:myInvocation withObject:nil];
#3
4
Use NSValue, like so:
使用NSValue,像这样:
+(void)method1:(SEL)selector {
NSValue *selectorValue = [NSValue value:&selector withObjCType:@encode(SEL)];
[NSThread detachNewThreadSelector:@selector(method2:)
toTarget:self
withObject:selectorValue];
}
NSValue is intended as an object-wrapper for arbitrary non-object types.
NSValue打算作为任意非对象类型的对象包装器。
#5
0
If you don't want to specify an object just use nil.
如果不想指定对象,就使用nil。
[NSThread detachNewThreadSelector:@selector(method:) toTarget:self withObject:nil];
If you need to pass an object to the selector it would look something like this.
如果需要将一个对象传递给选择器,它应该是这样的。
Here I'm passing a string to the method "setText".
这里我将一个字符串传递给方法“setText”。
NSString *string = @"hello world!";
[NSThread detachNewThreadSelector:@selector(setText:) toTarget:self withObject:string];
-(void)setText:(NSString *)string {
[UITextField setText:string];
}
#1
67
The problem here isn't passing a selector to a method, per se, but passing a selector where an object is expected. To pass a non-object value as an object, you can use NSValue
. In this case, you'll need to create a method that accepts an NSValue and retrieves the appropriate selector. Here's an example implementation:
这里的问题不是将选择器传递给方法本身,而是将选择器传递给预期的对象。要将非对象值作为对象传递,可以使用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
#2
41
You can convert between selectors and string objects using the NSStringFromSelector()
and NSSelectorFromString()
functions. So you can just pass string objects instead.
您可以使用NSStringFromSelector()和NSSelectorFromString()函数在选择器和字符串对象之间进行转换。所以你可以只传递字符串对象。
Alternately, if you don't want to change your methods, you can create an NSInvocation
to create an invocation for your method call (since it can set up invocations with non-object arguments), and then to call it do [NSThread detachNewThreadSelector:@selector(invoke) toTarget:myInvocation withObject:nil];
或者,如果您不想更改方法,您可以创建一个nsincall来为您的方法调用创建一个调用(因为它可以用非对象参数设置调用),然后调用它do [NSThread detachNewThreadSelector:@selector:@selector(调用)toTarget:myInvocation withObject:nil];
#3
4
Use NSValue, like so:
使用NSValue,像这样:
+(void)method1:(SEL)selector {
NSValue *selectorValue = [NSValue value:&selector withObjCType:@encode(SEL)];
[NSThread detachNewThreadSelector:@selector(method2:)
toTarget:self
withObject:selectorValue];
}
NSValue is intended as an object-wrapper for arbitrary non-object types.
NSValue打算作为任意非对象类型的对象包装器。
#4
#5
0
If you don't want to specify an object just use nil.
如果不想指定对象,就使用nil。
[NSThread detachNewThreadSelector:@selector(method:) toTarget:self withObject:nil];
If you need to pass an object to the selector it would look something like this.
如果需要将一个对象传递给选择器,它应该是这样的。
Here I'm passing a string to the method "setText".
这里我将一个字符串传递给方法“setText”。
NSString *string = @"hello world!";
[NSThread detachNewThreadSelector:@selector(setText:) toTarget:self withObject:string];
-(void)setText:(NSString *)string {
[UITextField setText:string];
}