如何使用performSelectorInBackground调用带有多个params的方法?
示例方法:
-(void) reloadPage:(NSInteger)pageIndex firstCase:(BOOL)firstCase;
答案 0 :(得分:38)
问题是performSelectorInBackground:withObject:
只接受一个对象参数。解决此限制的一种方法是将参数的字典(或数组)传递给“包装器”方法,该方法解构参数并调用实际方法:
- (void)callingMethod {
NSDictionary * args = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInteger:pageIndex], @"pageIndex",
[NSNumber numberWithBool:firstCase], @"firstCase",
nil];
[self performSelectorInBackground:@selector(reloadPageWrapper:)
withObject:args];
}
- (void)reloadPageWrapper:(NSDictionary *)args {
[self reloadPage:[[args objectForKey:@"pageIndex"] integerValue]
firstCase:[[args objectForKey:@"firstCase"] boolValue]];
}
- (void)reloadPage:(NSInteger)pageIndex firstCase:(BOOL)firstCase {
// Your code here...
}
这样你只是将“单个”参数传递给后台调用,但是该方法可以构造真实调用所需的多个参数(这将在同一个后台运行的线程上进行)。
答案 1 :(得分:6)
我刚刚发现了这个问题,对任何答案都不满意。在我看来,两者都没有充分利用可用的工具,并且在数组和字典中传递任意信息一般都让我担心。
所以,我去写了一个小NSObject
类,它将调用一个带有可变数量参数的任意选择器:
类别标题
@interface NSObject (NxAdditions)
-(void)performSelectorInBackground:(SEL)selector withObjects:(id)object, ... NS_REQUIRES_NIL_TERMINATION;
@end
类别实施
@implementation NSObject (NxAdditions)
-(void)performSelectorInBackground:(SEL)selector withObjects:(id)object, ...
{
NSMethodSignature *signature = [self methodSignatureForSelector:selector];
// Setup the invocation
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
invocation.target = self;
invocation.selector = selector;
// Associate the arguments
va_list objects;
va_start(objects, object);
unsigned int objectCounter = 2;
for (id obj = object; obj != nil; obj = va_arg(objects, id))
{
[invocation setArgument:&obj atIndex:objectCounter++];
}
va_end(objects);
// Make sure to invoke on a background queue
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithInvocation:invocation];
NSOperationQueue *backgroundQueue = [[NSOperationQueue alloc] init];
[backgroundQueue addOperation:operation];
}
@end
<强>用法强>
-(void)backgroundMethodWithAString:(NSString *)someString array:(NSArray *)array andDictionary:(NSDictionary *)dict
{
NSLog(@"String: %@", someString);
NSLog(@"Array: %@", array);
NSLog(@"Dict: %@", dict);
}
-(void)someOtherMethod
{
NSString *str = @"Hello world";
NSArray *arr = @[@(1337), @(42)];
NSDictionary *dict = @{@"site" : @"Stack Overflow",
@"url" : [NSURL URLWithString:@"http://stackoverflow.com"]};
[self performSelectorInBackground:@selector(backgroundMethodWithAString:array:andDictionary:)
withObjects:str, arr, dict, nil];
}
答案 2 :(得分:5)
好吧,我用过这个:
[self performSelectorInBackground:@selector(reloadPage:)
withObject:[NSArray arrayWithObjects:pageIndex,firstCase,nil] ];
为此:
- (void) reloadPage: (NSArray *) args {
NSString *pageIndex = [args objectAtIndex:0];
NSString *firstCase = [args objectAtIndex:1];
}
答案 3 :(得分:0)
你只能传递一个参数,所以为这个方法创建一个自定义对象来保存你的数据,它比一个模糊的字典或数组更简洁。这样做的好处是,当完成包含多个返回属性时,您可以传递相同的对象。
#import <Foundation/Foundation.h>
@interface ObjectToPassToMethod : NSObject
@property (nonatomic, strong) NSString *inputValue1;
@property (nonatomic, strong) NSArray *inputArray;
@property (nonatomic) NSInteger returnValue1;
@property (nonatomic) NSInteger returnValue2;
@end
并将该对象传递给您的方法:
ObjectToPassToMethod *obj = [[ObjectToPassToMethod alloc] init];
obj.inputArray = @[];
obj.inputValue1 = @"value";
[self performSelectorInBackground:@selector(backgroundMethod:) withObject:obj];
-(void)backgroundMethod:(ObjectToPassToMethod*)obj
{
obj.returnValue1 = 3;
obj.returnValue2 = 90;
}
确保在完成后清理对象以防止内存泄漏