performSelectorInBackground有多个参数

ysn*_*nky 15 cocoa-touch objective-c

如何使用performSelectorInBackground调用具有多个params的方法?

样品方法:

-(void) reloadPage:(NSInteger)pageIndex firstCase:(BOOL)firstCase;
Run Code Online (Sandbox Code Playgroud)

Tim*_*Tim 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...
}
Run Code Online (Sandbox Code Playgroud)

这样,您只将"单个"参数传递给后台调用,但该方法可以构造实际调用所需的多个参数(将在同一个后台运行的线程上进行).


Ste*_*ord 6

我刚刚发现了这个问题,对任何答案都不满意.在我看来,既没有充分利用可用的工具,并且在数组和字典中传递任意信息通常让我担心.

所以,我去写了一个小类NSObject,它将调用一个带有可变数量参数的任意选择器:

类别标题

@interface NSObject (NxAdditions)

-(void)performSelectorInBackground:(SEL)selector withObjects:(id)object, ... NS_REQUIRES_NIL_TERMINATION;

@end
Run Code Online (Sandbox Code Playgroud)

类别实施

@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
Run Code Online (Sandbox Code Playgroud)

用法

-(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];
}
Run Code Online (Sandbox Code Playgroud)


Roo*_*ahi 5

好吧,我用过这个:

[self performSelectorInBackground:@selector(reloadPage:)
                       withObject:[NSArray arrayWithObjects:pageIndex,firstCase,nil] ];
Run Code Online (Sandbox Code Playgroud)

为了这:

- (void) reloadPage: (NSArray *) args {
    NSString *pageIndex = [args objectAtIndex:0];    
    NSString *firstCase = [args objectAtIndex:1];    
}
Run Code Online (Sandbox Code Playgroud)

  • 这将泄漏一个`NSArray`.你应该使用`[NSArray arrayWithObjects:...]`而不是`[[NSArray alloc] initWithObjects:...]`. (3认同)