在Objective C中,是否可以使用类外部的选择器?

时间:2022-01-24 17:57:53

For example I have a method that looks like this

例如,我有一个看起来像这样的方法

[self performSelectorOnMainThread:@selector(someMethod) 
                       withObject:data
                    waitUntilDone:YES];

In which "someMethod" is from another class. If it is possible, how can I do that? Also, I'd like to know how can I pass in the parameters.

其中“someMethod”来自另一个类。如果有可能,我该怎么做?另外,我想知道如何传递参数。

Assume that someMethod is defined as:

假设someMethod定义为:

- (void)someMethod:(NSData *)data otherArg:(NSString *)arg;

5 个解决方案

#1


3  

Yes you can call selector of another class as well.

是的,你也可以调用另一个类的选择器。

If selector is class method -

如果选择器是类方法 -

[ClassName performSelectorOnMainThread:@selector(someMethod:) 
                   withObject:data
                waitUntilDone:YES];

and method signature is something like -

和方法签名是这样的 -

+ (void)someMethod:(returntype)somearg

If selector is instance method -

如果selector是实例方法 -

[classInstance performSelectorOnMainThread:@selector(someMethod:) 
                   withObject:data
                waitUntilDone:YES];

and method signature is something like -

和方法签名是这样的 -

- (void)someMethod:(returntype)somearg

#2


3  

You need to replace self with an instance of the class that defines the method. Otherwise you will get an unrecognized selector error. Also, don't forget to put a colon ( : ) after someMethod if you are sending it an argument.

您需要将self替换为定义方法的类的实例。否则,您将收到无法识别的选择器错误。另外,如果你发送一个参数,不要忘记在someMethod之后放一个冒号(:)。

#3


1  

It depends. If 'self' inherits from the class that implements someMethod, then you can of course do that. But you can't send a message to an object whose class (or ancestor class) doesn't implement that method. (Well, you can, but expect an error.)

这取决于。如果'self'继承自实现someMethod的类,那么你当然可以这样做。但是,您无法向其类(或祖先类)未实现该方法的对象发送消息。 (嗯,你可以,但期待一个错误。)

The code snippet you show is similar to:

您显示的代码段类似于:

[self someMethod:data];

except that someMethod: will run on the main thread rather than whatever thread is currently executing. Looking at it that way may help you remember that the receiver (self in this case, but it could be a pointer to any object) has to implement the message you're sending.

除了someMethod:将在主线程上运行,而不是当前正在执行的任何线程。以这种方式查看它可能会帮助您记住接收器(在这种情况下是自我,但它可能是指向任何对象的指针)必须实现您正在发送的消息。

#4


0  

Instead of self, you replace that with the instance of the class you want to perform the selector on.

您可以将其替换为要在其上执行选择器的类的实例,而不是self。

#5


0  

The message you want to send takes two parameters, and there's no variant of performSelectorOnMainThread:... that passes two parameters with the message.

您要发送的消息有两个参数,并且没有performSelectorOnMainThread的变体:...传递带消息的两个参数。

The easiest way to do this is to use Grand Central Dispatch and a block. If you are sure that you will not do this on the main thread, you can do this:

最简单的方法是使用Grand Central Dispatch和一个街区。如果您确定不在主线程上执行此操作,则可以执行以下操作:

dispatch_sync(dispatch_get_main_queue(), ^{
    [otherObject someMethod:myData otherArg:@"my argument"];
});

But if you run that code when you're already on the main thread, that code will deadlock - your app will hang.

但是如果你已经在主线程上运行该代码,那么代码将会死锁 - 你的应用程序将会挂起。

If you might want to do it when you're already on the main thread, you have to be more careful to avoid deadlock. I'd do it like this:

如果您可能想要在主线程上执行此操作,则必须更加小心以避免死锁。我这样做:

dispatch_block_t block = ^{
    [otherObject someMethod:myData otherArg:@"my argument"];
};

if (dispatch_get_current_queue() == dispatch_get_main_queue()) {
    block();
} else {
    dispatch_sync(dispatch_get_main_queue(), block);
}

#1


3  

Yes you can call selector of another class as well.

是的,你也可以调用另一个类的选择器。

If selector is class method -

如果选择器是类方法 -

[ClassName performSelectorOnMainThread:@selector(someMethod:) 
                   withObject:data
                waitUntilDone:YES];

and method signature is something like -

和方法签名是这样的 -

+ (void)someMethod:(returntype)somearg

If selector is instance method -

如果selector是实例方法 -

[classInstance performSelectorOnMainThread:@selector(someMethod:) 
                   withObject:data
                waitUntilDone:YES];

and method signature is something like -

和方法签名是这样的 -

- (void)someMethod:(returntype)somearg

#2


3  

You need to replace self with an instance of the class that defines the method. Otherwise you will get an unrecognized selector error. Also, don't forget to put a colon ( : ) after someMethod if you are sending it an argument.

您需要将self替换为定义方法的类的实例。否则,您将收到无法识别的选择器错误。另外,如果你发送一个参数,不要忘记在someMethod之后放一个冒号(:)。

#3


1  

It depends. If 'self' inherits from the class that implements someMethod, then you can of course do that. But you can't send a message to an object whose class (or ancestor class) doesn't implement that method. (Well, you can, but expect an error.)

这取决于。如果'self'继承自实现someMethod的类,那么你当然可以这样做。但是,您无法向其类(或祖先类)未实现该方法的对象发送消息。 (嗯,你可以,但期待一个错误。)

The code snippet you show is similar to:

您显示的代码段类似于:

[self someMethod:data];

except that someMethod: will run on the main thread rather than whatever thread is currently executing. Looking at it that way may help you remember that the receiver (self in this case, but it could be a pointer to any object) has to implement the message you're sending.

除了someMethod:将在主线程上运行,而不是当前正在执行的任何线程。以这种方式查看它可能会帮助您记住接收器(在这种情况下是自我,但它可能是指向任何对象的指针)必须实现您正在发送的消息。

#4


0  

Instead of self, you replace that with the instance of the class you want to perform the selector on.

您可以将其替换为要在其上执行选择器的类的实例,而不是self。

#5


0  

The message you want to send takes two parameters, and there's no variant of performSelectorOnMainThread:... that passes two parameters with the message.

您要发送的消息有两个参数,并且没有performSelectorOnMainThread的变体:...传递带消息的两个参数。

The easiest way to do this is to use Grand Central Dispatch and a block. If you are sure that you will not do this on the main thread, you can do this:

最简单的方法是使用Grand Central Dispatch和一个街区。如果您确定不在主线程上执行此操作,则可以执行以下操作:

dispatch_sync(dispatch_get_main_queue(), ^{
    [otherObject someMethod:myData otherArg:@"my argument"];
});

But if you run that code when you're already on the main thread, that code will deadlock - your app will hang.

但是如果你已经在主线程上运行该代码,那么代码将会死锁 - 你的应用程序将会挂起。

If you might want to do it when you're already on the main thread, you have to be more careful to avoid deadlock. I'd do it like this:

如果您可能想要在主线程上执行此操作,则必须更加小心以避免死锁。我这样做:

dispatch_block_t block = ^{
    [otherObject someMethod:myData otherArg:@"my argument"];
};

if (dispatch_get_current_queue() == dispatch_get_main_queue()) {
    block();
} else {
    dispatch_sync(dispatch_get_main_queue(), block);
}