【问题标题】:Instance method not found warning, but working未找到实例方法警告,但有效
【发布时间】:2013-07-09 19:41:43
【问题描述】:

在我的实现模型中,我需要一些不同的文件,以及一些类似的方法。另外,我在NSMutableArray 中收集了不同类型的对象,并尝试像这样调用我的类似方法:

[[ArrayOfViews objectAtIndex:i] myMethodWithInt:'number' andExample:'char'];

但它给了我一个警告:

Instance method '...' not found (return type defaults to 'id')

我的代码有效,但我应该修复这个警告吗?

【问题讨论】:

  • 您应该始终尝试修复 C 和 Objective-C 代码库中的警告;它们通常表明存在严重(通常是致命的)问题。
  • 这就是我努力检测并修复它们的原因 =)

标签: objective-c methods nsmutablearray warnings


【解决方案1】:

你应该介绍类型:

MONType * obj = [ArrayOfViews objectAtIndex:i];

然后使用类型化变量调用方法:

[obj myMethodWithInt:<#number#> andExample:<#char#>];

抱怨的原因可能有很多。引入该类型将解决这些类别的问题,或者至少给您一个更有用的警告。具体来说,编译器看不到实例方法-myMethodWithInt:andExample:的声明。

您可能没有导入标头,或者声明了方法以使其在翻译中可见。

我的代码有效,但我是否必须修复此警告?

也许吧。有时它会“工作”。这相当于 C89 缺少函数原型,由于它们引起的所有问题而被逐步淘汰。因此,如果参数和返回类型与id 兼容(包括NSObject 子类),则隐式参数和返回类型可以工作。但如果它不匹配,那么您应该期待未定义的行为。您可以通过在程序中使用适当的导入和声明以及通过引入如上所示的类型来避免所有这些并引入有意义的类型检查。这很有用,因为编译器会在您工作和代码库发展时避免出现大量愚蠢的错误。

【讨论】:

  • 那么我如何检测数组元素的类型呢?所以对象采用数组元素的类型(可变)
  • @user2057209 你可以在很多情况下使用公共基础——例如,如果数组只有 NSString 和 NSMutableStrings,而你只需要 NSString API,你可以只使用 NSString 作为公共基础。否则,您将需要使用动态检查(例如-isKindOfClass:),这可能是“臭”的。在某些情况下,引入协议可以简化此过程。集合中动态类型的逻辑是:“你应该知道你往里面放了什么”。
  • 数组中的元素都来自不同的文件。所以他们都来自不同的班级。数组应该有大约一百个元素,因此很难测试-isKindOfClass: 是否运行:s 你不可能有像 [ArrayOfViews objectAtIndex:0] getClass]; 这样的进程。 (伪代码)替换它?
  • @user2057209 结构类型介绍说明:id obj = [array objectAtIndex:0]; \n if ([obj isKindOfClass:[NSArray class]]) { NSArray * array = obj; ...use it... } \n else if ([obj isKindOfClass:[NSString class]]) { NSString * string = obj; ...use it... }
  • 好的,我会试试你的解决方案。谢谢=)
【解决方案2】:

这可能只是在调用之前没有声明方法的情况。尝试将方法声明添加到类的接口部分。

【讨论】:

  • 不,因为它在另一个文件中。这就是为什么不在主体文件中声明方法是正常的。
【解决方案3】:

在您的 objectAtIndex 调用中添加类型转换以消除警告。这不是什么大问题,但是从 NSArray 中对返回进行类型转换是一种很好的做法。

基本上:

YourObjectType *yourObject = (YourObjectType*)[ArrayOfViews objectAtIndex:i];
[yourObject myMethodWithInt:'number' andExample:'char'];

【讨论】:

  • ([[ArrayOfViews objectAtIndex:0] class]*)[ArrayOfViews objectAtIndex:0] 替换 (YourObjectType*)[ArrayOfViews objectAtIndex:i] 应该不行吗?
  • :) 嗯,这是一个有趣的尝试,但不,我认为它会导致编译器错误。在我看来,如果你知道对象的方法签名,你也应该知道对象类型。
  • 你同意,它不起作用:/我不能像你第一次那样添加演员,而不仅仅是创建一个新对象?因为数组中的所有对象都来自不同的对象类型,这就是我使用数组的原因:/
  • 我同意在强类型变量中捕获 id 类型的值通常是个好主意,但您应该删除示例中的强制转换,因为它根本没有任何效果。
  • 顺便说一句,编译器将允许您调用当前在 id 类型的对象上可见的任何方法,因此使用局部变量并不能解决 OP 的问题。
【解决方案4】:

您需要为声明您要调用的一个或多个方法的标头添加一个#import 语句。

【讨论】:

  • 提问者提到该代码有效。如果他忘记了#import 语句,将会出现运行时错误。
  • @Sid 请解释缺少编译时声明如何触发运行时错误。
  • @user2057209 说你有一个#import 语句是没有意义的,除非你确定它引用的头文件。如果不检查标题的内容,即使这样也不是很有意义。如果导入的标头不包含您正在调用的方法的声明,您仍然会收到相同的警告消息。
  • 我已经导入了头文件,并且方法被声明到头文件中,这不是问题=)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多