是否可以在Objective-C中将方法作为参数传递?

时间:2023-01-15 23:06:11

I have a method that varies by a single method call inside, and I'd like to pass the method/signature of the method that it varies by as an argument... is this possible in Objective C or is that too much to hope for?

我有一个方法,通过单个方法调用内部变化,我想传递它作为参数变化的方法的方法/签名...这是可能的目标C或是太多希望对于?

3 个解决方案

#1


25  

NSInvocation is a class for wrapping up a method calls in an object. You can set a selector (method signature), set arguments by index. You can then set a target and call invoke to trigger the call, or leave the target unset and use invokeWithTarget: in a loop of some sort to call this on many objects.

NSInvocation是一个用于在对象中包装方法调用的类。您可以设置选择器(方法签名),按索引设置参数。然后,您可以设置目标并调用invoke以触发调用,或者保持目标未设置并使用invokeWithTarget:在某种循环中在许多对象上调用它。

I think it works a little like this:

我觉得它有点像这样:

NSInvocation *inv = [[NSInvocation alloc] init];
[inv setSelector:@selector(foo:bar:)];
[inv setArgument:123 atIndex:0];
[inv setArgument:456 atIndex:1];

for (MyClass *myObj in myObjects) {
  [inv invokeWithTarget:myObj];
}

Or if you dont want to pass invocation objects into this method you can use the SEL type to accept a selector (method signature).

或者,如果您不想将调用对象传递给此方法,则可以使用SEL类型接受选择器(方法签名)。

-(void)fooWithMethod:(SEL)selector;

Then assign the selector to an invocation object in order to call it on objects.

然后将选择器分配给调用对象,以便在对象上调用它。

#2


10  

Or if you're using the fooWithMethod:(SEL)selector approach, just do [myObject performSelector:selector] on it, if it has no other arguments.

或者,如果您正在使用fooWithMethod:(SEL)选择器方法,只需在其上执行[myObject performSelector:selector],如果它没有其他参数。

See NSObject for details.

有关详细信息,请参阅NSObject。

#3


3  

As said before you can pass the selector of the method you want to call. Using a selector there are different ways to actually call the method:

如前所述,您可以传递要调用的方法的选择器。使用选择器有不同的方法来实际调用该方法:

  1. using NSObjects performSelector:, performSelector:withObject: and performSelector:withObject:withObject: methods
  2. 使用NSObjects performSelector:,performSelector:withObject:和performSelector:withObject:withObject:methods
  3. using a NSInvocation object
  4. 使用NSInvocation对象
  5. or directly using objc_msgSend or objc_msgSend_stret
  6. 或直接使用objc_msgSend或objc_msgSend_stret
  7. using the IMP of that method which you can get using methodForSelector:
  8. 使用methodForSelector可以获得的方法的IMP:

Which one to use really depends on the situation. If the performance is not critical I’d go ahead with 1 if you need to pass in 0, 1 or 2 objects. If the performSelector:... methods don’t match I’d go with 2 or 3. Since setting up an NSInvocation object requires a lot of boilerplate code I prefer 3, but I guess that’s a matter of personal choice, unless there are performance issues.

使用哪一个真的取决于具体情况。如果性能不重要,如果你需要传递0,1或2个对象,我会继续1。如果performSelector:...方法不匹配,我会选择2或3.由于设置NSInvocation对象需要很多样板代码我更喜欢3,但我想这是个人选择的问题,除非有性能问题。

If the performance of those method calls does matter I’d use 3 or 4. 3 should be faster unless you can cache the IMPs. But depending on your code this may not be feasible or doesn’t really help. So here you must profile the code and see which one is better for you.

如果那些方法调用的性能确实很重要,我会使用3或4. 3除非你可以缓存IMP,否则应该更快。但是根据你的代码,这可能不可行或者没有真正帮助。所以在这里你必须分析代码,看看哪一个更适合你。

#1


25  

NSInvocation is a class for wrapping up a method calls in an object. You can set a selector (method signature), set arguments by index. You can then set a target and call invoke to trigger the call, or leave the target unset and use invokeWithTarget: in a loop of some sort to call this on many objects.

NSInvocation是一个用于在对象中包装方法调用的类。您可以设置选择器(方法签名),按索引设置参数。然后,您可以设置目标并调用invoke以触发调用,或者保持目标未设置并使用invokeWithTarget:在某种循环中在许多对象上调用它。

I think it works a little like this:

我觉得它有点像这样:

NSInvocation *inv = [[NSInvocation alloc] init];
[inv setSelector:@selector(foo:bar:)];
[inv setArgument:123 atIndex:0];
[inv setArgument:456 atIndex:1];

for (MyClass *myObj in myObjects) {
  [inv invokeWithTarget:myObj];
}

Or if you dont want to pass invocation objects into this method you can use the SEL type to accept a selector (method signature).

或者,如果您不想将调用对象传递给此方法,则可以使用SEL类型接受选择器(方法签名)。

-(void)fooWithMethod:(SEL)selector;

Then assign the selector to an invocation object in order to call it on objects.

然后将选择器分配给调用对象,以便在对象上调用它。

#2


10  

Or if you're using the fooWithMethod:(SEL)selector approach, just do [myObject performSelector:selector] on it, if it has no other arguments.

或者,如果您正在使用fooWithMethod:(SEL)选择器方法,只需在其上执行[myObject performSelector:selector],如果它没有其他参数。

See NSObject for details.

有关详细信息,请参阅NSObject。

#3


3  

As said before you can pass the selector of the method you want to call. Using a selector there are different ways to actually call the method:

如前所述,您可以传递要调用的方法的选择器。使用选择器有不同的方法来实际调用该方法:

  1. using NSObjects performSelector:, performSelector:withObject: and performSelector:withObject:withObject: methods
  2. 使用NSObjects performSelector:,performSelector:withObject:和performSelector:withObject:withObject:methods
  3. using a NSInvocation object
  4. 使用NSInvocation对象
  5. or directly using objc_msgSend or objc_msgSend_stret
  6. 或直接使用objc_msgSend或objc_msgSend_stret
  7. using the IMP of that method which you can get using methodForSelector:
  8. 使用methodForSelector可以获得的方法的IMP:

Which one to use really depends on the situation. If the performance is not critical I’d go ahead with 1 if you need to pass in 0, 1 or 2 objects. If the performSelector:... methods don’t match I’d go with 2 or 3. Since setting up an NSInvocation object requires a lot of boilerplate code I prefer 3, but I guess that’s a matter of personal choice, unless there are performance issues.

使用哪一个真的取决于具体情况。如果性能不重要,如果你需要传递0,1或2个对象,我会继续1。如果performSelector:...方法不匹配,我会选择2或3.由于设置NSInvocation对象需要很多样板代码我更喜欢3,但我想这是个人选择的问题,除非有性能问题。

If the performance of those method calls does matter I’d use 3 or 4. 3 should be faster unless you can cache the IMPs. But depending on your code this may not be feasible or doesn’t really help. So here you must profile the code and see which one is better for you.

如果那些方法调用的性能确实很重要,我会使用3或4. 3除非你可以缓存IMP,否则应该更快。但是根据你的代码,这可能不可行或者没有真正帮助。所以在这里你必须分析代码,看看哪一个更适合你。