简体   繁体   中英

Passing parameters to @selector in performSelectorInBackground?

I've read a about @selector but I couldn't find an answer to my question

I'm trying to pass parameters to @selector . this is a simple code about what I did :

- (void)viewDidLoad{
    [super viewDidLoad];

    NewsCell *cell = (NewsCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
    if (cell == nil){
        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"NewsCell" owner:self options:nil];
        cell = [nib objectAtIndex:0];
    }
    NSString *string = @"image.png";

    [self performSelectorInBackground:@selector(doSomeThing::) withObject:nil];
}

-(void) doSomeThing:(UITableViewCell *)newsCell imageName:(NSString *)imageName{
    NSLog(@"newsCell: %@", newsCell);
    NSLog(@"imageName: %@", imageName);
}

I've created new UITableViewCell called cell , it loads from another nib file called NewsCell

and created new string called string

The question is how to send cell and string as parameters to @selector in performSelectorInBackground , Any ideas ??

Thanks ..

You can pass only one parameter using performSelectorInBackground (using the withObject parameter).

If you want to doSomeThing in the background with two parameters, you can:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    [self doSomeThing:cell imageName:string];
});

By the way, if doSomeThing is going to eventually do a UI update, make sure to dispatch that back to the main queue:

-(void) doSomeThing:(UITableViewCell *)newsCell imageName:(NSString *)imageName {

    // do your slow stuff in the background here

    NSLog(@"newsCell: %@", newsCell);
    NSLog(@"imageName: %@", imageName);

    // now update your UI

    dispatch_async(dispatch_get_main_queue(), ^{
        // update your UI here
    });
}

And as a final caveat, if you're updating a cell asynchronously, if you want to be really careful, you may want to be sensitive to the fact that the cell may have scrolled off the screen by the time the asynchronous method completes (and worse, that the UITableView may have reused that cell for another row of the table). Thus, you might want to check to make sure the cell is still on screen. Thus, pass the indexPath parameter rather than the cell, and then use the UITableView method, cellForRowAtIndexPath , not to be confused with the very similarly named UITableViewDataSource method tableView:cellForRowAtIndexPath , to see if it's still visible:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    [self doSomeThing:indexPath imageName:string];
});

And then

-(void) doSomeThing:(NSIndexPath *)indexPath imageName:(NSString *)imageName {

    // do your slow stuff in the background here

    NSLog(@"newsCell: %@", newsCell);
    NSLog(@"imageName: %@", imageName);

    // now update your UI

    dispatch_async(dispatch_get_main_queue(), ^{
        UITableViewCell *newsCell = [self.tableView cellForRowAtIndexPath:indexPath];
        if (newsCell)
        {
            // the cell is still visible, so update your UI here
        }
    });
}

You can pass an NSDictionary* or an NSArray* to performSelectorInBackground :

-(void)viewDidLoad {
    // Blah blah 
    NSDictionary* params = @{@"cell": cell, @"image": string};
    [self performSelectorInBackground:@selector(doSomething:) withObject:params];
}

-(void)doSomething:(NSDictionary*)params {
    UITableViewCell* cell = params[@"cell"];
    NSString* image = params[@"image"];

    // Blah blah...
}

I personally prefer NSDictionary to NSArray as it looks clearer.

The question is how to send 'cell' and 'string' as parameters to @selector in performSelectorInBackground, Any ideas ??

You can't. @selector() is a compiler directive which simply converts whatever is between the parentheses into an Objective-C selector -- you can't give it any other parameters. I think what you really want to do is to invoke the selector with parameters. The method you're trying to use only allows for a single parameter; there's no way to provide more than one.

Use a block or invocation. That doesn't mean that you don't have other options, though. You can use a block, as Rob describes, or you can create an instance of NSInvocation, add the necessary parameters, set the selector and target, and call -invoke .

You can only send one parameter with performSelectorInBackground.

You'll have to do some re-architecturing of your code.

To pass one of the parameters you do:

[self performSelectInBackground:@selector(doSomething:) withObject:cell];

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM