Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/43.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 在performSelectorInBackground中将参数传递给@selector?_Ios_Iphone_Objective C_Cocoa Touch - Fatal编程技术网

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

Ios 在performSelectorInBackground中将参数传递给@selector?,ios,iphone,objective-c,cocoa-touch,Ios,Iphone,Objective C,Cocoa Touch,我读过一篇关于@选择器的文章,但我找不到我问题的答案 我正在尝试将参数传递给@selector。这是一段关于我所做工作的简单代码: - (void)viewDidLoad{ [super viewDidLoad]; NewsCell *cell = (NewsCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier]; if (cell == nil){ NSArr

我读过一篇关于
@选择器的文章,但我找不到我问题的答案

我正在尝试将参数传递给
@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);
}
我已经创建了名为
单元格的新UITableViewCell,它从另一个名为
NewsCell的nib文件加载

并创建了名为
string

问题是如何将
单元格
字符串
作为参数发送到性能选择器背景中的
@选择器
,有什么想法吗


谢谢。

使用
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
可能已将该单元格重新用于表的另一行)。因此,您可能需要检查以确保单元格仍在屏幕上。因此,传递
indepath
参数而不是单元格,然后使用
UITableView
方法,不要与名称非常相似的
UITableViewDataSource
方法混淆,以查看它是否仍然可见:

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

您可以将
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...
}

我个人更喜欢
NSDictionary
而不是
NSArray
,因为它看起来更清晰。

您只能发送一个带有performSelectorInBackground的参数

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

要传递其中一个参数,请执行以下操作:

[self performSelectInBackground:@selector(doSomething:) withObject:cell];
问题是如何在performSelectorInBackground中将“cell”和“string”作为参数发送给@selector,有什么想法吗

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


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

您已经正确设置了
doSomeThing:imageName
但需要更改使用
[doSomeThing:cell imageName:string]调用函数的方式
dispatch\u async
函数中。顺便说一句,我知道您可能试图通过在
viewDidLoad
中执行这些操作来简化示例,但您确实不应该在那里创建/更新单元格。此
dequeueReusableCellWithIdentifier
内容可能应该在
UITableViewDataSource
方法
tableView:CellForRowatingIndexPath
中执行,而不是在
viewDidLoad
中执行。看到了吗?@罗布,没错。。这段代码只是一个例子。。谢谢你,我从来没想过;)绝对是最好的解决方案,与此相比,伟大的答案
performSelectorInBackground
看起来相形见绌它应该是(dispatch\u async(dispatch\u get\u global\u queue(dispatch\u queue\u PRIORITY\u DEFAULT,0)是这样吗?我想你已经忘记了“,0”@Mujtababbas说得很对。我修改了我的答案。我只是在没有Xcode帮助的情况下输入了这个。)如果您不介意更改
-doSomething:imageName:
,使其只接受一个参数,或者提供另一种方法将字典转换为对
-doSomething:imageName:
的调用,那么这是很好的。我认为这不是“最好的”解决方案,虽然,因为它避免了OP询问的问题,而不是解决问题。嗯,我想这是
performSelectorInBackground
的一个限制。如果他们添加一个类似
performSelectorInBackground:withObject1:object2:
的版本就好了。但是他们没有……无论如何
doSomething
是一种方法OP拥有,所以不应该改变它。同意。这里有很多选项。如果<代码> DOWOMENTHON/COD>正在进行网络请求,我也可能建议他也可以考虑使用<代码> NSO操作队列< /COD>(他可以设置
maxConcurrentOperationCount
,这样如果在速度非常慢的网络上执行此操作,他就不会提交太多并发请求),这提供了GCD不具备的取消逻辑(这样他就不会冒着为可能已经很久没有滚动的单元格检索图像的风险,从而产生非常慢的UX)。