【问题标题】:receiver type *** for instance message is a forward declaration接收器类型 *** 例如消息是前向声明
【发布时间】:2023-10-17 04:00:02
【问题描述】:

在我的 iOS5 应用程序中,我有 NSObject States 类,并尝试初始化它:

states = [states init];

这是States中的init方法:

- (id) init
{
    if ((self = [super init]))
    {
        pickedGlasses = 0;
    }

    return self;
}

但是states = [states init];这一行有错误

接收者类型“状态”例如消息是前向声明

这是什么意思?我做错了什么?

【问题讨论】:

  • 我试图解决同样的问题,但每个人都有不同的解决方案。我有点困惑
  • 非常简短的回答是您要么缺少#import(可能在您的前缀文件中),要么缺少“@class Abc;”行(即在@interface 行上方的.h 文件中)
  • 还要确保这是否是一个 swift 类并且您使用的“@objc(ClassName)”该名称与您的类名定义相匹配。案件很重要。

标签: iphone ios objective-c forward-declaration


【解决方案1】:

这基本上意味着你需要导入包含States声明的.h文件。

但是,您的代码还有很多其他问题。

  • 你正在初始化一个没有+alloc的对象。那行不通
  • 您将对象声明为非指针类型,这也不起作用
  • 您没有在-init 中调用[super init]
  • 您已在标头中使用 @class 声明了该类,但从未导入该类。

【讨论】:

  • 这有点奇怪,因为在我的情况下,由于循环引用问题,我刚刚删除了 .h 文件。
  • 多么荒谬的措辞。但是,是的,这解决了它。
  • 如果你想在 Objective-C 中使用 Swift 对象,别忘了它们必须继承自 NSObject
  • 在#ifdef FB_SONARKIT_ENABLED 或#if DEBUG 中放置“MyProject-Swift.h”时,您也可能会收到此错误 - 然后它在模拟器中有效,但在构建版本时无效。
【解决方案2】:

FWIW,我在将核心数据实施到现有项目时遇到此错误。原来我忘记将 CoreData.h 链接到我的项目。我已经将 CoreData 框架添加到我的项目中,但通过链接到我的预编译头文件中的框架解决了这个问题,就像 Apple 的模板一样:

#import <Availability.h>

#ifndef __IPHONE_5_0
#warning "This project uses features only available in iOS SDK 5.0 and later."
#endif

#ifdef __OBJC__
    #import <UIKit/UIKit.h>
    #import <Foundation/Foundation.h>
    #import <CoreData/CoreData.h>
#endif

【讨论】:

  • 几乎所有的 CoreData 教程都是从使用模板开始而不是从现有项目开始的,这真是太可惜了。这里很容易出错。
【解决方案3】:

当我有两个相互依赖的文件时,我收到了这种消息。这里的棘手之处在于,如果您只是尝试从它们的头文件中相互导入(A 类导入 B 类,B 类导入 A 类),您将获得循环引用。因此,您要做的是将前向 (@class A) 声明放在一个类的(B 类)头文件中。但是,当尝试在 B 类的实现中使用 A 类的 ivar 时,就会出现这个错误,只需在 B 类的 .m 文件中添加一个 #import "A.h" 就可以解决我的问题。

【讨论】:

    【解决方案4】:

    我尝试使用@class "Myclass.h"

    当我将其更改为 #import "Myclass.h" 时,它运行良好。

    【讨论】:

    • 这里只是一个旁注:@class "Myclass.h" 完全不正确。 @class Myclass 应该在无法导入类的头文件中使用(由于循环引用,例如在 Objective-C 中使用 Swift 定义的类),但如果可以导入,则应该使用 #import "Myclass.h"
    【解决方案5】:

    如果您在 Objective C 中尝试使用 Swift 类或方法时遇到此错误:您忘记了 Apple 在此图中定义的两个步骤之一:

    示例:

    错误出现在您的Test.m 文件中:

    类消息的接收者“MyClass”是一个前向声明

    在 Obj-C 文件中:

    第 1 步:检查 Test.h 是否有

    @class MyClass;
    

    第 2 步:在 Build Settings 中找到 *-Swift.h 文件名(查找 Objective-C Generated Interface Header Name)。名称将类似于 MyModule-Swift.h

    第 3 步:检查 Test.m 是否导入了上述标头

    #import <MyModule/MyModule-Swift.h>
    

    在 Swift 文件中:

    • 确保MyClass(或其基类)继承NSObject 类。
    • 确保 @objc 在您希望从 Obj-C 调用的每个方法之前。
    • 另外,检查Target Membership部分(在文件检查器中)。

    【讨论】:

      【解决方案6】:

      你正在使用

      States states;
      

      你应该在哪里使用

      States *states;
      

      你的init方法应该是这样的

      -(id)init {
        if( (self = [super init]) ) {
            pickedGlasses = 0;
        }
        return self;
      }
      

      现在,当你要为 States 类创建一个对象时,你应该这样做。

      State *states = [[States alloc] init];
      

      我并不是说这是最好的方法。但它可能会帮助您了解初始化对象的最基本用法。

      【讨论】:

        【解决方案7】:

        检查是否导入了引发此错误的类的头文件。

        【讨论】:

          【解决方案8】:

          确保您的单元方法的原型在 .h 文件中。

          因为您在文件中调用的方法比您定义的更高,所以您会收到此消息。或者,您可以重新排列您的方法,使调用者在文件中的位置低于他们调用的方法。

          【讨论】:

            【解决方案9】:

            有两个相关的错误消息可能会告诉您声明和/或导入有问题。

            第一个是您所指的那个,它可以通过在您的 .h 中声明 @class 时不在您的 .m(或 .pch 文件)中放入 #import 来生成。

            如果您的 States 类中有一个方法,您可能会看到第二个:

            - (void)logout:(NSTimer *)timer
            

            添加#import后是这样的:

            “States”没有可见的@interface 声明选择器“注销:”

            如果您看到这一点,您需要检查并查看您是否在要导入或转发的类的 .h 文件中声明了“注销”方法(在本例中)。

            所以在你的情况下,你需要一个:

            - (void)logout:(NSTimer *)timer;
            

            在您的 States 类的 .h 中,使这些相关错误中的一个或两个消失。

            【讨论】: