iOS - 如何使用多个参数和 afterDelay 实现一个 performSelector?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8439052/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
iOS - How to implement a performSelector with multiple arguments and with afterDelay?
提问by Suchi
I am an iOS newbie. I have a selector method as follows -
我是iOS新手。我有一个选择器方法如下 -
- (void) fooFirstInput:(NSString*) first secondInput:(NSString*) second
{
}
I am trying to implement something like this -
我正在尝试实现这样的东西 -
[self performSelector:@selector(fooFirstInput:secondInput:) withObject:@"first" withObject:@"second" afterDelay:15.0];
But that gives me an error saying -
但这给了我一个错误说-
Instance method -performSelector:withObject:withObject:afterDelay: not found
Any ideas as to what I am missing?
关于我缺少什么的任何想法?
回答by valvoline
Personally, I think that a closer solution to your needs is the use of NSInvocation.
就个人而言,我认为更接近您需求的解决方案是使用 NSInvocation。
Something like the following will do the work:
像下面这样的东西将完成这项工作:
indexPathand dataSourceare two instance variables defined in the same method.
indexPath和dataSource是在同一个方法中定义的两个实例变量。
SEL aSelector = NSSelectorFromString(@"dropDownSelectedRow:withDataSource:");
if([dropDownDelegate respondsToSelector:aSelector]) {
NSInvocation *inv = [NSInvocation invocationWithMethodSignature:[dropDownDelegate methodSignatureForSelector:aSelector]];
[inv setSelector:aSelector];
[inv setTarget:dropDownDelegate];
[inv setArgument:&(indexPath) atIndex:2]; //arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation
[inv setArgument:&(dataSource) atIndex:3]; //arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation
[inv invoke];
}
回答by Michael Dautermann
Because there is no such thing as a [NSObject performSelector:withObject:withObject:afterDelay:]
method.
因为没有[NSObject performSelector:withObject:withObject:afterDelay:]
方法这样的东西。
You need to encapsulate the data you want to send along into some single Objective C object (e.g. a NSArray, a NSDictionary, some custom Objective C type) and then pass it through the[NSObject performSelector:withObject:afterDelay:]
method that is well known and loved.
您需要将要发送的数据封装到某个单一的Objective C 对象(例如NSArray、NSDictionary、某些自定义Objective C 类型)中,然后通过[NSObject performSelector:withObject:afterDelay:]
众所周知和喜爱的方法传递它。
For example:
例如:
NSArray * arrayOfThingsIWantToPassAlong =
[NSArray arrayWithObjects: @"first", @"second", nil];
[self performSelector:@selector(fooFirstInput:)
withObject:arrayOfThingsIWantToPassAlong
afterDelay:15.0];
回答by Firoze Lafeer
You can package your parameters into one object and use a helper method to call your original method as Michael, and others now, have suggested.
您可以将参数打包到一个对象中,并使用辅助方法调用您的原始方法,正如 Michael 和其他人现在所建议的那样。
Another option is dispatch_after, which will take a block and enqueue it at a certain time.
另一个选项是dispatch_after,它将在某个时间获取一个块并将其入队。
double delayInSeconds = 15.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[self fooFirstInput:first secondInput:second];
});
Or, as you've already discovered, if you don't require the delay you can just use - performSelector:withObject:withObject:
或者,正如您已经发现的,如果您不需要延迟,您可以使用 - performSelector:withObject:withObject:
回答by aroth
The simplest option is to modify your method to take a single parameter containing both arguments, such as an NSArray
or NSDictionary
(or add a second method that takes a single parameter, unpacks it, and calls the first method, and then call the secondmethod on a delay).
最简单的方法是修改你的方法把含有两个参数,比如一个参数NSArray
或NSDictionary
(或添加只有一个参数,拆包,并调用第一种方法第二种方法,然后调用第二个上的方法延迟)。
For instance, you could have something like:
例如,你可以有类似的东西:
- (void) fooOneInput:(NSDictionary*) params {
NSString* param1 = [params objectForKey:@"firstParam"];
NSString* param2 = [params objectForKey:@"secondParam"];
[self fooFirstInput:param1 secondInput:param2];
}
And then to call it, you can do:
然后调用它,你可以这样做:
[self performSelector:@selector(fooOneInput:)
withObject:[NSDictionary dictionaryWithObjectsAndKeys: @"first", @"firstParam", @"second", @"secondParam", nil]
afterDelay:15.0];
回答by Mike Wallace
- (void) callFooWithArray: (NSArray *) inputArray
{
[self fooFirstInput: [inputArray objectAtIndex:0] secondInput: [inputArray objectAtIndex:1]];
}
- (void) fooFirstInput:(NSString*) first secondInput:(NSString*) second
{
}
and call it with:
并调用它:
[self performSelector:@selector(callFooWithArray) withObject:[NSArray arrayWithObjects:@"first", @"second", nil] afterDelay:15.0];
回答by StilesCrisis
You can find all the types of provided performSelector: methods here:
您可以在此处找到提供的所有类型的 performSelector: 方法:
There are a bunch of variations but there isn't a version that takes multiple objects as well as a delay. You'll need to wrap up your arguments in an NSArray or NSDictionary instead.
有很多变体,但没有一个版本需要多个对象以及延迟。您需要将参数封装在 NSArray 或 NSDictionary 中。
- performSelector:
- performSelector:withObject:
- performSelector:withObject:withObject:
– performSelector:withObject:afterDelay:
– performSelector:withObject:afterDelay:inModes:
– performSelectorOnMainThread:withObject:waitUntilDone:
– performSelectorOnMainThread:withObject:waitUntilDone:modes:
– performSelector:onThread:withObject:waitUntilDone:
– performSelector:onThread:withObject:waitUntilDone:modes:
– performSelectorInBackground:withObject:
回答by BB9z
I dislike the NSInvocation way, too complex. Let's keep it simple and clean:
我不喜欢 NSInvocation 的方式,太复杂了。让我们保持简单和干净:
// Assume we have these variables
id target, SEL aSelector, id parameter1, id parameter2;
// Get the method IMP, method is a function pointer here.
id (*method)(id, SEL, id, id) = (void *)[target methodForSelector:aSelector];
// IMP is just a C function, so we can call it directly.
id returnValue = method(target, aSelector, parameter1, parameter2);
回答by darkfader
I just did some swizzling and needed to call the original method. What I did was making a protocol and cast my object to it. Another way is to define the method in a category, but would need suppression of a warning (#pragma clang diagnostic ignored "-Wincomplete-implementation").
我只是做了一些调整,需要调用原始方法。我所做的是制定一个协议并将我的对象投向它。另一种方法是在类别中定义方法,但需要抑制警告(#pragma clang 诊断忽略“-Wincomplete-implementation”)。
回答by Kappe
A simple and reusable way is to extend NSObject
and implement
一种简单且可重用的方式是扩展NSObject
和实现
- (void)performSelector:(SEL)aSelector withObjects:(NSArray *)arguments;
something like:
就像是:
- (void)performSelector:(SEL)aSelector withObjects:(NSArray *)arguments
{
NSMethodSignature *signature = [self methodSignatureForSelector: aSelector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature: signature];
[invocation setSelector: aSelector];
int index = 2; //0 and 1 reserved
for (NSObject *argument in arguments) {
[invocation setArgument: &argument atIndex: index];
index ++;
}
[invocation invokeWithTarget: self];
}
回答by MobileMon
I would just create a custom object holding all my parameters as properties, and then use that single object as the parameter
我只是创建一个自定义对象,将我的所有参数作为属性,然后使用该单个对象作为参数