15

This is ridiculous, im trying to create a sound bool to turn of in app sounds. I keep getting

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

I have checked that all my files are linked in build phases, I have deleted the appdelegate .m where im getting the error before I even get to call the bool in any of my view controllers, and re imported it in build phases. Checked I have relevant framweworks in place. I have even checked a previous app I made with same code and the code it appears to be exactly the same with no error (built with previous version of xcode). Taking it right back to basics I get the error as soon as I add the following code to my App Delegate,

.h

#import <UIKit/UIKit.h>
extern NSString *kPlaySoundPrefsKey;

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

@end

.m

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

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:    (NSDictionary *)launchOptions
 {

NSDictionary *defaultDict = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES]
 forKey:kPlaySoundPrefsKey];

return YES;
}

If I change extern NSString *kPlaySoundPrefsKey; to NSString *kPlaySoundPrefsKey; it builds then crashes...Im out of ideas now

JSA986
  • 5,870
  • 9
  • 45
  • 91

4 Answers4

18

When you declaring something as extern you are telling the compiler the type AND that you will define it somewhere else. In your case you never define your variable.

So in your .h you would have:

extern NSString* kPlaySoundPrefsKey;

But in some .m you must also have

NSString* kPlaySoundPrefsKey = @"play_sounds"; // or some value

Since in your case these are constants you can also specify:

extern NSString* const kPlaySoundPrefsKey;

and

NSString* const kPlaySoundPrefsKey = @"play_sounds"; 

The addition of the const qualifier will cause a compiler error if someone ever writes something like

kPlaySoundPrefsKey = @"some_other_value";
idz
  • 12,825
  • 1
  • 29
  • 40
7

I am also got the same error even if I am properly declared and define the extern const string , The problem is, my constant file not in the compile source list .

Make sure that your .m file appears in the "Compile Sources" Build Phase for your build target. Sometimes, adding files to a project in Xcode doesn't add all implementation files to the appropriate targets.

Hope this will helpful for some people. Refe: linker-error-undefined-symbols-symbols-not-found

Community
  • 1
  • 1
Raj
  • 5,895
  • 4
  • 27
  • 48
4

First, ensure it is defined:

// AppDelegate.h
extern NSString* const kPlaySoundPrefsKey; // << declaration

// AppDelegate.m
NSString * const kPlaySoundPrefsKey = @"kPlaySoundPrefsKey";  // << definition

see also:

"extern const" vs "extern" only

3 questions about extern used in an Objective-C project

Linker error using extern "C" in Objective-C code

Community
  • 1
  • 1
justin
  • 104,054
  • 14
  • 179
  • 226
  • 1
    I down voted the original answer because it did not address the root cause of the OP's problem; he was never defining the variable. Once you edited it to address this I removed it. – idz Aug 30 '12 at 01:32
  • @idz alright. i received two separate anon downvotes (which have both been undone now), one of which came *after* the update which mentioned the absence definition. so, i found it a bit unusual. thank you for the explanation. – justin Aug 30 '12 at 01:44
  • Does C++ name mangle variables? I thought it only did that with functions. – JeremyP Aug 31 '12 at 09:52
  • @JeremyP in this case (toolchain+abi+etc.), the exported name is the same. will remove that part. cheers. – justin Aug 31 '12 at 20:46
  • Could you explain about the usage of `extern` here, it doesn't seem constant in the Apple header files to have this. Sometimes there is only `NSString *const`, other times `extern NSString *const`, and sometimes `extern NSString *` – Daniel Mar 14 '13 at 21:14
  • @Daniel a) could you provide an example header b+c) the only difference is that c may be assigned another string -- the string it 'points to' may be set during execution. for a pref key or notification name, it should be `const` – justin Mar 14 '13 at 22:38
  • 1
    ninja downvoters? lol! long time @justin it's good to see your answers again :) – abbood Apr 28 '14 at 13:13
0

Thanks for your help guys

I added

NSString *kPlaySoundPrefsKey = @"playSoundKey";

[[NSUserDefaults standardUserDefaults] registerDefaults:defaultDict];

to app delegate. That fixed it

JSA986
  • 5,870
  • 9
  • 45
  • 91