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)。