4

我有一个专为 iPhone OS 2.x 设计的应用程序。

在某些时候我有这个代码

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

但是由于 initWithFrame 选择器在 3.0 中已被弃用,我需要使用 respondToSelector 和 performSelector... 转换此代码...

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

我的问题是:如果我必须传递两个参数“initWithFrame:CGRectZero”和“reuseIdentifier:myIdentifier”,如何将 A 上的调用分解为 preformSelector 调用?

编辑 - 按照 fbrereto 的建议,我这样做了

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

我遇到的错误是“'performSelector:withObject:withObject' 的参数 2 的类型不兼容

myIdentifier 是这样声明的

static NSString *myIdentifier = @"Normal";

我试图将呼叫更改为

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

没有成功...

另一点是 CGRectZero 不是一个对象......

4

2 回答 2

11

使用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];

或者,objc_msgSend直接调用(跳过所有不必要的复杂高级构造):

cell = objc_msgSend(cell, @selector(initWithFrame:reuseIdentifier:), 
                    CGRectZero, myIdentifier);
于 2010-03-06T18:32:06.063 回答
1

您要使用的选择器实际上是@selector(initWithFrame:reuseIdentifier:). 要传递两个参数,请使用performSelector:withObject:withObject:. 获得正确的参数可能需要一些试验和错误,但它应该可以工作。如果不是,我建议探索NSInvocation旨在处理更复杂的消息调度的类。

于 2010-03-06T17:53:49.817 回答