Reputation: 6116
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 ..
Upvotes: 2
Views: 1553
Reputation: 437882
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
}
});
}
Upvotes: 10
Reputation: 125007
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
.
Upvotes: 2
Reputation: 2116
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];
Upvotes: 0
Reputation: 11132
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.
Upvotes: 5