【问题标题】:Why performSelector:withObject: methods can only take id?为什么 performSelector:withObject: 方法只能取 id?
【发布时间】:2011-03-21 13:46:43
【问题描述】:

在 Objective-C 中,所有执行选择器的方法都是这样的:

 - performSelector:withObject:
 - makeObjectsPerformSelector:withObject:
 - performSelectorInBackground:withObject:

并且只能在参数中获取id(指针)对象?你知道为什么吗 ?那是从 C 继承的东西,并且使用线程我们需要一个指针吗?


编辑: 而在 Objective-C 中我们不能直接创建指针。如果我想用指针做类似下面的事情,这是否有效? (我知道 NSNumber 和 NSValue 类,但我只是想了解它是如何工作的)

int i = 5;
int *pointer_i = &i;
[self performSelector:mySelector withObject:pointer_i];

【问题讨论】:

  • 啊!!你可以说它需要一个 void * 类型的参数。但我仍然在这里理解你的问题。
  • @Praveen S 每个id 都是一个指针,但不是每个void * 都是id

标签: iphone objective-c c ios pointers


【解决方案1】:

您只能将指针作为参数,因此objective-c 对象。如果你想使用整数,试试这个:

int i;
[self performSelector:@selector(mySelector:) withObject:[NSNumber numberWithInt:i]];

【讨论】:

  • 是的,我知道(我更新了关于 Objective-C 中指针的问题)。
  • 那么还有什么问题呢?只需使用 NSNumber 而不是直接 int。 int 是一个原始类型,不使用指针,而 NSNumber 是一个对象,可以包含任何类型的原始数字,并且是一个指针。
  • 嗯,那你应该也可以在 Objective-c 中使用它,我想。不过没听说过。当我自己遇到这个问题时,所有提示都指向使用 NSNumber。我会检查是否可以在 int 指针上找到任何内容。
  • id 类型意味着这些方法可以采用任何类型的对象。这并不意味着您可以将任何您喜欢的旧指针类型传递给它们。
  • 是的。 id 是指向任何 object(Obj-C 类的实例)的指针。请参阅此处的 id 部分developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/…
【解决方案2】:

您可以投射withObject:(id)pointer_i,但这是一个坏主意
在这个特定的例子中,withObject: 的参数是retained。如果你传入一个int *,而该方法需要一个id,你的程序将会崩溃,因为它正在尝试retain一个int

【讨论】:

  • 好的,谢谢!我刚刚看到,如果我用我的 int 创建一个 NSNumber,并在我的函数中尝试显示它,它会显示一个奇怪的数字。 NSLog(@"我的号码:%i", i);打印:1073752700 是指针地址?
  • 您将格式说明符 %i 用于 int。您应该切换到使用%@ 对象描述说明符或使用[i intValue]
【解决方案3】:

因为 id 是指向任何类型对象的指针。所以你不需要知道你得到了什么类型的对象(NSString,NSArray)。 id 可以指向任何东西。

【讨论】:

  • 那么,我假设我使用 int 指针进行的编辑工作正常吗? Xcode 说“与参数 'id' 不兼容的指针类型 'int *'”。我们知道 'id' 是 'void *',所以我可以将指针投射到 'id' 中,它会起作用吗?
  • 将任意指针(如 int *)传递给需要对象指针的接口是自找麻烦。即使它现在看起来“工作”,但它是不正确的,并且很容易在后续的操作系统版本中中断。
  • 我会改写成id 是指向NSObject 的任何子类的指针,而不是“指向任何类型对象的指针”。您绝对不能将id 视为void*。你不能做 OP 试图做的事情并传递一个 int * (好吧,你可以绕过它并做到这一点,但它一点也不聪明)
【解决方案4】:

基本上你可以传入任何单个对象(如果你需要那种灵活性,它本身可以是一个数组或字典,但你当然需要能够在你调用的函数中传递它。

不过,我留下这个答案的原因是要提到一个陷阱,它让我在使用它时感到沮丧。如果您在选择器名称后省略冒号,应用程序将编译但会在运行时崩溃。

使用前面的例子

[self performSelector:@selector(mySelector:) withObject:[NSNumber numberWithInt:i]];

"mySelector:" 需要冒号。

好吧,也许这是一件小事,对核心程序员来说是显而易见的,但我花了很多时间来调试它。如果您的代码崩溃并且您传递的对象是有效的,那么选择器可能不是。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多