iPhone - 如何使用具有复杂参数的 performSelector?

Posted

技术标签:

【中文标题】iPhone - 如何使用具有复杂参数的 performSelector?【英文标题】:iPhone - how to use performSelector with complex parameters? 【发布时间】:2010-03-06 17:37:27 【问题描述】:

我有一个专为 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 不是一个对象...

【问题讨论】:

【参考方案1】:

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

【讨论】:

谢谢。我已经使用了你的代码,但我在你的代码的第一行有一个 EXC_BAD_ACCESS。我想,原因是在最初的调用中,一个 ALLOC 正在完成,并且由于某种原因,我不确定这个方法是否正在分配单元......我已经尝试了你的第二种方法,我有同样的错误。 我已经找到了解决方案。您的代码几乎是完美的。唯一缺少的是首先分配单元格。谢谢!【参考方案2】:

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

【讨论】:

我不确定您是否可以通过 performSelector 传递 CGRect:根本:它们不是对象。 感谢您的回答。我已经更新了问题以显示我所做的以及我遇到的错误。 Chpwn 在这里也有一个好点...... CGRect 不是一个对象......这正在融化我的大脑...... @chpwn:好点;那么,NSInvocation 似乎是最好的(唯一的?)选择。

以上是关于iPhone - 如何使用具有复杂参数的 performSelector?的主要内容,如果未能解决你的问题,请参考以下文章

如何让 perl 正确传递具有多个参数和复杂文件路径(空格和符号)的命令行参数?

perf record/report

perf record/report

如何解读perf属性中的LLC-Load-Misses

如何使用 linux perf 工具进行代码理解

我如何使用 perf 来分析我的代码?