在performSelectorInBackground中将参数传递给@selector?

时间:2013-06-24 15:09:27

标签: ios iphone objective-c cocoa-touch

我读了一篇关于@selector但我无法找到问题的答案

我正在尝试将参数传递给@selector。这是一个关于我所做的简单代码:

- (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);
}

我创建了名为cell的新 UITableViewCell ,它从另一个名为NewsCell nib 文件加载

并创建了名为string

的新字符串

问题是如何将cellstring作为参数发送到 performSelectorInBackground 中的@selector,任何想法?

谢谢..

4 个答案:

答案 0 :(得分:10)

您只能使用performSelectorInBackground传递一个参数(使用withObject参数)。

如果您想在后台使用两个参数doSomeThing,您可以:

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

顺便说一下,如果doSomeThing最终要进行UI更新,请确保将其重新发送回主队列:

-(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
    });
}

作为最后的警告,如果你要异步更新一个单元格,如果你想要非常小心,你可能想要对异步方法时单元格可能已经滚出屏幕的事实敏感。完成(更糟糕的是,UITableView可能已将该单元格重用于该表的另一行)。因此,您可能需要检查以确保单元格仍在屏幕上。因此,传递indexPath参数而不是单元格,然后使用UITableView方法cellForRowAtIndexPath,不要与名称相似的UITableViewDataSource方法{{3}混淆,看看它是否仍然可见:

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

然后

-(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
        }
    });
}

答案 1 :(得分:5)

您可以将NSDictionary*NSArray*传递给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...
}

我个人更喜欢NSDictionaryNSArray,因为它看起来更清晰。

答案 2 :(得分:2)

  

问题是如何将'cell'和'string'作为参数发送到performSelectorInBackground中的@selector,任何想法?

你不能。 @selector()是一个编译器指令,它只是将括号中的任何内容转换为Objective-C选择器 - 你不能给它任何其他参数。我认为你真正想做的是用参数调用选择器。您尝试使用的方法只允许使用单个参数;没有办法提供多个。

使用块或调用。但这并不意味着您没有其他选项。您可以像Rob描述的那样使用块,或者您可以创建NSInvocation的实例,添加必要的参数,设置选择器和目标,然后调用-invoke

答案 3 :(得分:0)

您只能使用performSelectorInBackground发送一个参数。

您必须对代码进行一些重新构建。

要传递其中一个参数:

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