【问题标题】:I am having all the time this issue after running my app运行我的应用程序后,我一直遇到这个问题
【发布时间】:2012-07-16 15:59:07
【问题描述】:

我不知道为什么,但在没有问题的情况下工作了一段时间后,我添加了一些按钮,然后我启动了我的应用程序并出现了这个错误:

ld:重复符号 _x in /Users/alexbarco/Library/Developer/Xcode/DerivedData/RecolectaDatos-ayjpqqcajbhuzvbkvernzsyunpbe/Build/Intermediates/RecolectaDatos.build/Debug-iphonesimulator/RecolectaDatos.build/Objects-normal/i386/SeconViewController.o 和 /Users/alexbarco/Library/Developer/Xcode/DerivedData/RecolectaDatos-ayjpqqcajbhuzvbkvernzsyunpbe/Build/Intermediates/RecolectaDatos.build/Debug-iphonesimulator/RecolectaDatos.build/Objects-normal/i386/ViewController.o 对于架构 i386 clang:错误:链接器命令失败并退出 代码 1(使用 -v 查看调用)

【问题讨论】:

    标签: objective-c ios


    【解决方案1】:

    每当我有重复的符号错误时,几乎总是因为我的标题中有一个循环#import。解决方案非常简单,尽可能使用前向声明,并从 .m 文件中 #import .h 文件。

    只有两种情况你需要从另一个.h 中#import 一个:

    1. 如果您在#import 中扩展类
    2. 您正在实现#import 中的协议

    具体来说,您不需要仅仅为了在您的签名中使用类名或协议而导入文件;而是使用前向声明。

    例如,这个(在 Bar.h 中):

    #import "Foo.h"
    

    可能会变成这样(Bar.h):

    @class Foo;
    @protocol FooDelegate;
    

    和bar.m:

    #import "Foo.h"
    

    这是the documentation on forward declarations 的链接。

    【讨论】:

    • “使用前向声明”是什么意思?
    • 正如我在回答中所展示的,Objective-C 允许您告诉编译器一个类或协议“将在运行时存在”,或者基本上,“不要抱怨你找不到这个班级”。语法很简单,只要用@class Foo;告诉编译器“相信我,有这样一个类型,比如Foo,它是一个类”,还有`@protocol FooDelegate;'说“相信我,有一个名为“FooDelegate”的协议。它们允许您在方法签名和@property 声明中使用这些标识符,而无需#import 它们实际存在的文件。跨度>
    • 我仍然有问题...链接器命令失败,退出代码为 1(使用 -v 查看调用)
    • duplicate symbol _x 的内容相同吗?
    • 而且,您是否从应用程序的各个角落彻底删除了#import 声明(尽可能)?
    【解决方案2】:

    “重复符号”消息意味着您在同一范围内两次声明某个名称(在本例中为 _x)。假设你有这样的代码:

    int _x = 1;
    int _x = 2;
    

    那么你应该会得到一个错误,对吧?您可以同时为两件事使用相同的名称。

    您遇到的错误基本相同。你在某处声明_x,从编译器的角度来看,你做了两次。有几种方法可以解决这个问题,具体取决于 _x 所代表的含义。

    chrahey 的回答解释了前向类声明。我在这里不再赘述,只是说前向声明可以帮助您解决循环引用,其中 A 类的定义取决于 B 类,反之亦然。

    如果_x 是一个变量,很可能您正试图在头文件中声明它。编译器基本上会将您导入的每个头文件的内容复制到源文件中,因此如果您在头文件中声明一个变量,然后将该头文件导入两个或多个实现文件,您最终会得到多个声明多变的。为了解决这个问题,使用extern 关键字告诉编译器“这个名称将在其他地方声明”,然后将真正的声明放在一个实现文件中:

    Foo.h:

    extern int _x;
    

    Foo.m

    int _x;
    

    函数也差不多。 _x 似乎不是一个函数,但如果是,并且如果你愚蠢地将函数定义放在头文件中,那么如果该文件被导入超过一个实现文件。这就是为什么头文件包含原型而不是定义的原因:

    Foo.h:

    int foo(int a);
    

    Foo.m

    int foo(int a)
    {
        return a + 10;
    }
    

    【讨论】:

      猜你喜欢
      • 2021-05-04
      • 2021-12-30
      • 1970-01-01
      • 1970-01-01
      • 2021-11-02
      • 1970-01-01
      • 1970-01-01
      • 2021-12-17
      • 1970-01-01
      相关资源
      最近更新 更多