Xcode - 在 AppDelegate 中加载声音时出现 Apple Mach-O 链接器错误

Posted

技术标签:

【中文标题】Xcode - 在 AppDelegate 中加载声音时出现 Apple Mach-O 链接器错误【英文标题】:Xcode - Apple Mach-O Linker errors when loading sound in AppDelegate 【发布时间】:2015-02-08 23:37:49 【问题描述】:

我目前的应用设置如下:

我在 AppDelegate.h 中设置了一个 extern 变量,因为我读过它们充当全局变量。还添加了 AudioToolbox 框架。

AppDelegate.h

#import <UIKit/UIKit.h>
#import <AudioToolbox/AudioToolbox.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

extern SystemSoundID tapSoundID;

@end

接下来,我在 AppDelegate 的 didFinishLaunching 方法中添加了加载敲击声音的代码,因为我希望在应用启动后立即加载声音。

AppDelegate.m

#import "AppDelegate.h"
@interface AppDelegate ()
@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
    // Override point for customization after application launch.

    // Load Tap Sound
    NSURL *tapSoundPath = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"tap" ofType:@"mp3"]];
    AudioservicesCreateSystemSoundID((__bridge CFURLRef)tapSoundPath, &tapSoundID);
    return YES;


@end

确保在我的标题屏幕视图控制器中导入 AppDelegate.h 类。

TitleScreen.h

#import <UIKit/UIKit.h>
#import "AppDelegate.h"

最后,我使用AudioServicesPlaySystemSound(tapSoundID); 在点击按钮时播放声音。

TitleScreen.m

#import "TitleScreen.h"
@interface TitleScreen ()
@end

@implementation TitleScreen

- (IBAction)buttonToGameScreen:(id)sender
    AudioServicesPlaySystemSound(tapSoundID);


@end

老实说,我认为这会起作用,在我尝试运行应用程序之前,Xcode 没有显示任何警告或错误:

构建失败:Apple Mach-O 链接器错误

Undefined symbols for architecture armv7:
  "_tapSoundID", referenced from:
      -[AppDelegate application:didFinishLaunchingWithOptions:] in AppDelegate.o
      -[TitleScreen goToGameplay:] in TitleScreen.o
ld: symbol(s) not found for architecture armv7
clang: error: linker command failed with exit code 1 (use -v to see invocation)

我不知道这些错误是什么意思。我是 Objective-C/iOS 编程的新手,我花了几个小时试图自己解决这个问题,但我就是做不到。请帮忙。

【问题讨论】:

您的意思是在TitleScreen.h 中有一个@interface 吗? 【参考方案1】:

extern SystemSoundID tapSoundID 没有定义tapSoundID。它只是意味着它是在其他地方定义的。

所以让我们把它放在你的 AppDelegate.m 文件中。

#import "AppDelegate.h"

SystemSoundID tapSoundID; // Add this 

@interface AppDelegate ()
@end

而且我认为链接错误会消失。

您也可以看看这篇文章,它很好地解释了extern 的使用。

3 questions about extern used in an Objective-C project

【讨论】:

感谢您的快速回复。 Mach-O 错误消失了,但现在我在 TitleScreen.h 的 AudioServicePlaySystemSound(tapSoundID); 行上得到了一个 Use of undeclared identifier 'tapSoundID' 哦,我现在明白了,我认为我必须从 .h 文件中删除 extern SystemSoundID tapSoundID; 时遇到错误。我将它添加回 .h 并在 .m 文件中定义了它,一切都按照我现在想要的方式工作!非常感谢您的帮助和链接~【参考方案2】:

你误解了如何使用全局变量。

你声明了一个没有 extern 关键字的全局变量:

SystemSoundID tapSoundID;

但是,如果您只是将定义更改为此,您将收到“重复符号”链接器错误。原因如下。

#import 指令类似于复制和粘贴。预处理后,AppDelegate.m 将如下所示:

//a few hundred thousand lines of code from UIKit and AudioToolbox here

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

SystemSoundID tapSoundID;

@end


@interface AppDelegate ()
@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
    // Override point for customization after application launch.

    // Load Tap Sound
    NSURL *tapSoundPath = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"tap" ofType:@"mp3"]];
    AudioServicesCreateSystemSoundID((__bridge CFURLRef)tapSoundPath, &tapSoundID);
    return YES;


@end

TitleScreen.m 看起来像这样:

//a few hundred thousand lines of code from UIKit and AudioToolbox here

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

SystemSoundID tapSoundID;

@end

@interface TitleScreen ()
@end

@implementation TitleScreen

- (IBAction)buttonToGameScreen:(id)sender
    AudioServicesPlaySystemSound(tapSoundID);


@end

注意项目现在如何包含tapSoundID 的两个定义?这就是“重复符号”链接器错误的原因。如果你想让一个全局变量在整个程序中都可以访问,你需要保留

extern SystemSoundID tapSoundID;

AppDelegate.h 中,但您还必须在AppDelegate.m 中声明全局变量(不带extern):

SystemSoundID tapSoundID;

@implementation AppDelegate
//...

extern 关键字告诉链接器全局变量是在另一个文件中定义的。当您仅使用extern 声明变量时,链接器会查找实际定义,但找不到它,从而导致“未定义符号”错误。使用AppDelegate.h 中的extern 定义AppDelegate.m 中的全局变量,链接器可以看到AppDelegate.m 中的变量,并使其可供包括AppDelegate.h 的所有文件访问。 p>

【讨论】:

感谢您的解释。 Yuchen 在上面的回答中提到了它,但我花了一分钟才意识到我需要两者。您的帖子进一步澄清了这一点。

以上是关于Xcode - 在 AppDelegate 中加载声音时出现 Apple Mach-O 链接器错误的主要内容,如果未能解决你的问题,请参考以下文章

无法在 AppDelegate 应用程序方法的数组中加载 HTTP POST 响应数据。如何解决这个问题?

在核心数据项目中加载视图控制器时出现问题

需要从 appdelegate 加载 UIViewController 并在 Storyboard App 中加载时隐藏 UITabBarController

Xcode App 有时不会加载视图

在组objective-c Xcode中加载文件

如何修复 @testable 导入无法在 xcode 单元测试中加载模块