由于循环引用导致链接器 "Duplicate Symbol" 错误

Linker "Duplicate Symbol" error due to circular reference

我有两个 header 的 class 和它的扩展名(由 Xcode 为 NSManaged object 生成)。但是我收到链接器错误,我发现这是由于循环引用造成的。

对话+CoreDataClass.h

NS_ASSUME_NONNULL_BEGIN

@interface Conversation : NSManagedObject

@end

NS_ASSUME_NONNULL_END

#import "Conversation+CoreDataProperties.h"

对话+CoreDataProperties.h

#import "Conversation+CoreDataClass.h"

NS_ASSUME_NONNULL_BEGIN

@interface Conversation (CoreDataProperties)

+ (NSFetchRequest<Conversation *> *)fetchRequest;

@end

NS_ASSUME_NONNULL_END

你可以清楚地看到这里的循环引用。我发现此 question 问题在于添加 @class 声明并删除 header。所以我把Conversation+CoreDataProperties.h里的import语句注释掉,加上@class Conversation;。现在弹出两个错误,说它是未定义的 class。已附上以下错误的屏幕截图。我不太明白为什么会发生这种情况以及我需要做些什么来解决它。任何帮助深表感谢。谢谢!

链接器错误

duplicate symbol _OBJC_CLASS_$_Conversation in: /Users/xxx/Library/Developer/Xcode/DerivedData/xxx-gbhivuwptwzhkldfbmjghkokozgn/Build/Intermediates/xxx.build/Debug-iphoneos/xxx.build/Objects-normal/arm64/Conversation+CoreDataClass.o duplicate symbol _OBJC_METACLASS_$_Conversation in: /Users/xxx/Library/Developer/Xcode/DerivedData/xxx-gbhivuwptwzhkldfbmjghkokozgn/Build/Intermediates/xxx.build/Debug-iphoneos/xxx.build/Objects-normal/arm64/Conversation+CoreDataClass.o duplicate symbol _OBJC_CLASS_$_ConversationDate in: /Users/xxx/Library/Developer/Xcode/DerivedData/xxx-gbhivuwptwzhkldfbmjghkokozgn/Build/Intermediates/xxx.build/Debug-iphoneos/xxx.build/Objects-normal/arm64/ConversationDate+CoreDataClass.o duplicate symbol _OBJC_METACLASS_$_ConversationDate in: /Users/xxx/Library/Developer/Xcode/DerivedData/xxx-gbhivuwptwzhkldfbmjghkokozgn/Build/Intermediates/xxx.build/Debug-iphoneos/xxx.build/Objects-normal/arm64/ConversationDate+CoreDataClass.o ld: 4 duplicate symbols for architecture arm64 clang: error: linker command failed with exit code 1 (use -v to see invocation)

So I commented out the import statement in the Conversation+CoreDataProperties.h and added @class Conversation;.

如果您没有使用任何 Convention class 的接口(例如声明 属性 类型 Convention。如果您通过类别或 class 扩展名扩展 Convention,则无法执行此操作。

你这里有一个合法的循环引用你必须解决。您可以:

  1. 将 class 和类别移动到同一个源文件中(如果没有特殊原因需要将其放在类别中,您可以将 fetchRequest 的声明移动到 class本身)。
  2. 停止在 class header 中导入 +CoreDataProperties.h,而是在调用者需要调用 fetchRequest.
  3. 的任何地方导入它

重复符号警告的结果是因为

  1. 你的项目中有多次class,编译器不知道该选择哪个(那么多半是重复链接错误)
  2. 你的ConversationDate+CoreDataClass
  3. 有问题

只是从您的源代码中提出的一个问题:为什么要导入要扩展的 class 的扩展?

#import "Conversation+CoreDataClass.h"
@interface Conversation (CoreDataProperties)

+ (NSFetchRequest<Conversation *> *)fetchRequest;

@end

所有扩展 class 通常需要知道的基本上是它们扩展的 classes:

#import "Conversation.h"
@interface Conversation (CoreDataProperties)

+ (NSFetchRequest<Conversation *> *)fetchRequest;

@end

只有实现文件 (.m) 需要导入头文件。例如:

#import "Conversation+CoreDataClass.h"
@implementation Conversation (CoreDataProperties)

+ (NSFetchRequest<Conversation *> *)fetchRequest { 
    // body
    return nil;
}

@end

最后一个问题:您确定您的项目中不存在其他 class 同名扩展吗? CoreData 也可能自己创建了它们。

请像这样查看您的 xCode 项目:

在此 answer 中找到了解决我的问题的方法。我只需要从 Compile Sources 中删除 .m 文件。