2015-02-08 50 views
0

加載聲音時我現在有我的應用程序的設置是這樣的:的Xcode - 蘋果的Mach-O鏈接錯誤,在AppDelegate中

我設置在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中沒有表現出任何警告或錯誤,直到我試圖運行應用程序:

構建失敗:蘋果Mach-O Linker錯誤

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編程的新手,我花了好幾個小時試圖自己弄清楚這一點,但我不能。請幫忙。

+0

你的意思是在'TitleScreen.h'中有'@ interface'嗎? – NobodyNada 2015-02-08 23:52:32

回答

3

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

+0

感謝您的快速回復。 Mach-O錯誤消失了,但是現在我在TitleScreen.h的'AudioServicePlaySystemSound(tapSoundID)'行中得到'使用未聲明的標識符'tapSoundID''。 – user3781632 2015-02-08 23:47:13

+1

哦,我現在看到了,我得到了那個錯誤,認爲我必須從.h文件中刪除'extern SystemSoundID tapSoundID;'。我將它添加回.h文件,並在.m文件中進行了定義,一切都按我想要的方式運行!非常感謝幫助和鏈接〜 – user3781632 2015-02-08 23:54:12

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 

通知該項目現在怎麼樣包含2點定義爲tapSoundID?這是「重複符號」鏈接器錯誤的原因。如果你想有一個全局變量是在整個程序的訪問,你需要保持

extern SystemSoundID tapSoundID; 
AppDelegate.h

,但你也必須聲明全局變量(不extern)在AppDelegate.m

SystemSoundID tapSoundID; 

@implementation AppDelegate 
//... 

extern關鍵字告訴鏈接器該全局變量是在另一個文件中定義的。當您僅使用extern聲明變量時,鏈接器查找實際定義,但找不到它,導致「未定義符號」錯誤。通過AppDelegate.h中的extern定義AppDelegate.m中的全局變量,鏈接器會看到AppDelegate.m中的變量,並使其可以訪問包含AppDelegate.h的所有文件。

+0

感謝您的解釋。雨辰在上面的回答中提到了它,但花了我一分鐘才意識到我需要兩個。你的帖子進一步澄清了。 – user3781632 2015-02-09 00:00:20