views:

705

answers:

2

I have an application designed for iPhone OS 2.x.

At some point I have this code

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

  //... previous stuff initializing the cell and the identifier

  cell = [[[UITableViewCell alloc] 
     initWithFrame:CGRectZero 
     reuseIdentifier:myIdentifier] autorelease]; // A


  // ... more stuff
}

But as the initWithFrame selector was deprecated in 3.0, I need to transform this code using respondToSelector and performSelector... as this...

if ( [cell respondsToSelector:@selector(initWithFrame:)] ) { // iphone 2.0
  // [cell performSelector:@selector(initWithFrame:) ... ???? what?
}

My problem is: how can I break the call on A into preformSelector calls if I have to pass two parameters "initWithFrame:CGRectZero" and "reuseIdentifier:myIdentifier" ???

EDIT - As sugested by fbrereto, I did this

 [cell performSelector:@selector(initWithFrame:reuseIdentifier:)
    withObject:CGRectZero 
    withObject:myIdentifier];

The error I have is "incompatible type for argument 2 of 'performSelector:withObject:withObject'.

myIdentifier is declared like this

static NSString *myIdentifier = @"Normal";

I have tried to change the call to

 [cell performSelector:@selector(initWithFrame:reuseIdentifier:)
    withObject:CGRectZero 
    withObject:[NSString stringWithString:myIdentifier]];

without success...

The other point is CGRectZero not being an object...

+1  A: 

The selector you are looking to use is actually @selector(initWithFrame:reuseIdentifier:). To pass two parameters use performSelector:withObject:withObject:. It may take a little trial and error to get the parameters just right, but it should work. If it does not I would recommend exploring the NSInvocation class which is intended to handle more complicated message dispatching.

fbrereto
I'm not sure you can pass CGRects via performSelector: at all: they aren't objects.
chpwn
thanks for the answer. I have updated the question to show what I have did and the error I am experiencing. Chpwn has also a good point here... CGRect are not an object... this is melting my brain...
Digital Robot
@chpwn: good point; it would seem NSInvocation would be the best (only?) choice here, then.
fbrereto
+6  A: 

Use NSInvocation.

 NSInvocation* invoc = [NSInvocation invocationWithMethodSignature:
                        [cell methodSignatureForSelector:
                         @selector(initWithFrame:reuseIdentifier:)]];
 [invoc setTarget:cell];
 [invoc setSelector:@selector(initWithFrame:reuseIdentifier:)];
 CGRect arg2 = CGRectZero;
 [invoc setArgument:&arg2 atIndex:2];
 [invoc setArgument:&myIdentifier atIndex:3];
 [invoc invoke];

Alternatively, call objc_msgSend directly (skipping all the unnecessary complex high-level constructs):

cell = objc_msgSend(cell, @selector(initWithFrame:reuseIdentifier:), 
                    CGRectZero, myIdentifier);
KennyTM
Thanks. I have used your code but I am having a EXC_BAD_ACCESS on the first line of your code. The reason, I suppose, is that on the original call an ALLOC was being done and, for some reason, I am not sure if this method is allocating the cell... I have tried your second method I have the same error.
Digital Robot
I have discovered the solution. Your code is almost perfect. The only thing missing is allocating the cell first. Thanks!
Digital Robot