Declaring extern NSString causes linker error - objective-c

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

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";

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

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

Thanks for your help guys
I added
NSString *kPlaySoundPrefsKey = #"playSoundKey";
[[NSUserDefaults standardUserDefaults] registerDefaults:defaultDict];
to app delegate. That fixed it

Related

updated advice on setting constants in Objective-C?

I read through the advice here Constants in Objective-C, but I find two errors in the accepted answer:
I keep getting linker errors when I implement the approach of using .m and .h
In my constants.m file, I get the error "unknown type" for NSString
I am also getting an error following the advice from #VictorHanHee
as a further suggestion of how to link the constants to a .pch file:
I don't have a .pch file by default, and when I create a new one it
doesn't have the formatting expected from the answer.
All I have done is create constants.h and constants.m and put the constant declarations in them as provided in the accepted answer. I also created a .pch file, but as I said it doesn't at all match VictorHanHee's description.
Is this older posting outdated, or if not what am I missing? I don't really know how to go forward with a linker error. I simply want to have a file constants.h where I declare all constants and can include this file in as many classes as I want to make life easier. Can someone tell me how to do this nowadays or point to a more recent discussion?
Also here is the linker error (or part of log I can copy and paste anyway, not full message)
-[AccountInfoViewController viewDidLoad] in AccountInfoViewController.o
ld: symbol(s) not found for architecture armv7
clang: error: linker command failed with exit code 1 (use -v to see invocation)
As you can see, I am trying to access the constant from viewDidLoad. I am simply trying to print it out with NSLog.
Here are the .h and .m files I was originally using:
.h
extern NSString * const PREFS_MY_CONSTANT;
.m
NSString * const PREFS_MY_CONSTANT = #"prefs_my_constant";
Ok here is the template that actually seems to work:
.h
#ifndef Project_prefs_h
#define Project_prefs_h
#endif
extern NSString * const PREFS_MY_CONSTANT;
.m
#import <Foundation/Foundation.h>
NSString * const PREFS_MY_CONSTANT = #"prefs_my_constant";
So the older post is perhaps misleading or I misunderstood them when they said remove everything apart from the constants - but if you don't actually want to remove everything, shouldn't you say so? That's a fair amount of text in there not to mention...
In recent version of Xcode there is no ProjectName-Prefix.pch created automatically file so you should import the file where it is required then try using the constant.
Easiest way:
// Prefs.h
#import <Foundation/Foundation.h>
#define PREFS_MY_CONSTANT #"prefs_my_constant"
Better way:
// Prefs.h
extern NSString * const PREFS_MY_CONSTANT;
// Prefs.m
NSString * const PREFS_MY_CONSTANT = #"prefs_my_constant";
There are a few different ways to create constants in Objective-C, but the easiest way is to use #define statements.
To start, create a new header file. This is where we’ll store all the constants. Name it something original like “Constants.h”.
Here’s a sample file with a few constants:
//
// Constants.h
// App Name
#import <Foundation/Foundation.h>
#define NUM_SECTIONS 7
#define NUM_SECTION_1_ITEMS 2
#define NUM_SECTION_2_ITEMS 14
#define NUM_SECTION_3_ITEMS 5
#define APP_TITLE #"App Name"
#define APP_AUTHOR #"Miscellanea"
To use these constants in your project, you need to import your header file in each implementation file (*.m) where you’ll be referencing them.
#import "Constants.h"
– (void)viewDidLoad
{
self.title = APP_TITLE;
for (int i = 0; i < NUM_SECTIONS; ++ i)
{
// etc.
}
}
Here is the template that does seem to work. It's not different from the old answer except that you don't delete everything apart from the constants.
.h
#ifndef Project_prefs_h
#define Project_prefs_h
#endif
extern NSString * const PREFS_MY_CONSTANT;
.m
#import <Foundation/Foundation.h>
NSString * const PREFS_MY_CONSTANT = #"prefs_my_constant";
Apart from this it appears no longer possible to use .pch file to automatically include the constants across all classes.

How to find unused ivars in Xcode

Sometimes I declare an ivar but after a while I am no longer using it. I would like to remove this sort of cruft from my code, but I cannot find a warning that will show me my unused ivars.
Is there a tool or built in feature of Xcode that will allow me to find all of my unused ivars?
I see that the static analyzer has CLANG_ANALYZER_OBJC_UNUSED_IVARS, but it does not seem to do anything.
#implementation AppDelegate
{
#private
BOOL _foo; // Never read or written to
}
Runing the analyzer in Xcode 5 with CLANG_ANALYZER_OBJC_UNUSED_IVARS (unused ivars) set to YES never produces a warning.
Based on the relevant Clang source code and a couple of quick tests, it seems that the analyzer does not look at ivars that are not both declared in the #interface and marked #private.
#interface Igloo : NSObject
{
NSString * address; // No warning
#private
NSInteger radius; // Warning
}
#end
#implementation Igloo
{
NSInteger numWindows; // No warning
#private // Has no real effect, of course; just testing
NSString * doormatText; // No warning
}
#end
I suggest filing a bug/submitting a patch.
It appears that the static analyzer option only works if you declare the ivar in the header file.
This generates the analyzer warning correctly:
// AppDelegate.h
#interface AppDelegate : NSObject <UIApplicationDelegate>
{
BOOL _foo; // never read or written
}
#end
Neither of these generates any sort of analyzer warning:
// AppDelegate.m
#interface AppDelegate ()
{
#private
BOOL _goo; // never read or written
}
#end
#implementation AppDelegate
{
#private
BOOL _hoo; // never read or written
}
#end
So it looks like you cannot use the modern syntax to keep ivars in the .m file if you want to check for unused ivars.
In Xcode from product menu click on analyze... It will show you unused variables. This will also tell you about dead code.

Extending the XCTestCase class in Xcode [duplicate]

Here is the error message I receive when compiling ...
Ld /Users/ilia3546/Library/Developer/Xcode/DerivedData/MasterDetail-fhgogwnbpzovbtaskgecptdnvgjs/Build/Products/Debug-iphonesimulator/MasterDetail.app/MasterDetail normal i386
cd /Users/ilia3546/Проекты/iDecide
setenv IPHONEOS_DEPLOYMENT_TARGET 5.0
setenv PATH "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin"
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -arch i386 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator6.0.sdk -L/Users/ilia3546/Library/Developer/Xcode/DerivedData/MasterDetail-fhgogwnbpzovbtaskgecptdnvgjs/Build/Products/Debug-iphonesimulator -F/Users/ilia3546/Library/Developer/Xcode/DerivedData/MasterDetail-fhgogwnbpzovbtaskgecptdnvgjs/Build/Products/Debug-iphonesimulator -filelist /Users/ilia3546/Library/Developer/Xcode/DerivedData/MasterDetail-fhgogwnbpzovbtaskgecptdnvgjs/Build/Intermediates/MasterDetail.build/Debug-iphonesimulator/MasterDetail.build/Objects-normal/i386/MasterDetail.LinkFileList -Xlinker -objc_abi_version -Xlinker 2 -fobjc-link-runtime -Xlinker -no_implicit_dylibs -mios-simulator-version-min=5.0 -framework UIKit -framework Foundation -framework CoreGraphics -o /Users/ilia3546/Library/Developer/Xcode/DerivedData/MasterDetail-fhgogwnbpzovbtaskgecptdnvgjs/Build/Products/Debug-iphonesimulator/MasterDetail.app/MasterDetail
duplicate symbol _main in:
/Users/ilia3546/Library/Developer/Xcode/DerivedData/MasterDetail-fhgogwnbpzovbtaskgecptdnvgjs/Build/Intermediates/MasterDetail.build/Debug-iphonesimulator/MasterDetail.build/Objects-normal/i386/main-E0BAF2CA88EDEE32.o
duplicate symbol _OBJC_IVAR_$_MasterDetailAppDelegate._window in:
/Users/ilia3546/Library/Developer/Xcode/DerivedData/MasterDetail-fhgogwnbpzovbtaskgecptdnvgjs/Build/Intermediates/MasterDetail.build/Debug-iphonesimulator/MasterDetail.build/Objects-normal/i386/MasterDetailAppDelegate-C2C06F734ECE2E36.o
duplicate symbol _OBJC_IVAR_$_MasterDetailAppDelegate._navigationController in:
/Users/ilia3546/Library/Developer/Xcode/DerivedData/MasterDetail-fhgogwnbpzovbtaskgecptdnvgjs/Build/Intermediates/MasterDetail.build/Debug-iphonesimulator/MasterDetail.build/Objects-normal/i386/MasterDetailAppDelegate-C2C06F734ECE2E36.o
duplicate symbol _OBJC_IVAR_$_MasterDetailAppDelegate._splitViewController in:
/Users/ilia3546/Library/Developer/Xcode/DerivedData/MasterDetail-fhgogwnbpzovbtaskgecptdnvgjs/Build/Intermediates/MasterDetail.build/Debug-iphonesimulator/MasterDetail.build/Objects-normal/i386/MasterDetailAppDelegate-C2C06F734ECE2E36.o
duplicate symbol _OBJC_CLASS_$_MasterDetailAppDelegate in:
/Users/ilia3546/Library/Developer/Xcode/DerivedData/MasterDetail-fhgogwnbpzovbtaskgecptdnvgjs/Build/Intermediates/MasterDetail.build/Debug-iphonesimulator/MasterDetail.build/Objects-normal/i386/MasterDetailAppDelegate-C2C06F734ECE2E36.o
duplicate symbol _OBJC_METACLASS_$_MasterDetailAppDelegate in:
/Users/ilia3546/Library/Developer/Xcode/DerivedData/MasterDetail-fhgogwnbpzovbtaskgecptdnvgjs/Build/Intermediates/MasterDetail.build/Debug-iphonesimulator/MasterDetail.build/Objects-normal/i386/MasterDetailAppDelegate-C2C06F734ECE2E36.o
duplicate symbol _OBJC_IVAR_$_MasterDetailDetailViewController._detailItem in:
/Users/ilia3546/Library/Developer/Xcode/DerivedData/MasterDetail-fhgogwnbpzovbtaskgecptdnvgjs/Build/Intermediates/MasterDetail.build/Debug-iphonesimulator/MasterDetail.build/Objects-normal/i386/MasterDetailDetailViewController-B3C32DC7B1BE4E38.o
duplicate symbol _OBJC_IVAR_$_MasterDetailDetailViewController._TitleOfDetail in:
/Users/ilia3546/Library/Developer/Xcode/DerivedData/MasterDetail-fhgogwnbpzovbtaskgecptdnvgjs/Build/Intermediates/MasterDetail.build/Debug-iphonesimulator/MasterDetail.build/Objects-normal/i386/MasterDetailDetailViewController-B3C32DC7B1BE4E38.o
duplicate symbol _OBJC_IVAR_$_MasterDetailDetailViewController._detailDescriptionLabel in:
/Users/ilia3546/Library/Developer/Xcode/DerivedData/MasterDetail-fhgogwnbpzovbtaskgecptdnvgjs/Build/Intermediates/MasterDetail.build/Debug-iphonesimulator/MasterDetail.build/Objects-normal/i386/MasterDetailDetailViewController-B3C32DC7B1BE4E38.o
duplicate symbol _OBJC_IVAR_$_MasterDetailDetailViewController._masterPopoverController in:
/Users/ilia3546/Library/Developer/Xcode/DerivedData/MasterDetail-fhgogwnbpzovbtaskgecptdnvgjs/Build/Intermediates/MasterDetail.build/Debug-iphonesimulator/MasterDetail.build/Objects-normal/i386/MasterDetailDetailViewController-B3C32DC7B1BE4E38.o
duplicate symbol _OBJC_IVAR_$_MasterDetailDetailViewController.WebView in:
/Users/ilia3546/Library/Developer/Xcode/DerivedData/MasterDetail-fhgogwnbpzovbtaskgecptdnvgjs/Build/Intermediates/MasterDetail.build/Debug-iphonesimulator/MasterDetail.build/Objects-normal/i386/MasterDetailDetailViewController-B3C32DC7B1BE4E38.o
duplicate symbol _OBJC_CLASS_$_MasterDetailDetailViewController in:
/Users/ilia3546/Library/Developer/Xcode/DerivedData/MasterDetail-fhgogwnbpzovbtaskgecptdnvgjs/Build/Intermediates/MasterDetail.build/Debug-iphonesimulator/MasterDetail.build/Objects-normal/i386/MasterDetailDetailViewController-B3C32DC7B1BE4E38.o
duplicate symbol _OBJC_METACLASS_$_MasterDetailDetailViewController in:
/Users/ilia3546/Library/Developer/Xcode/DerivedData/MasterDetail-fhgogwnbpzovbtaskgecptdnvgjs/Build/Intermediates/MasterDetail.build/Debug-iphonesimulator/MasterDetail.build/Objects-normal/i386/MasterDetailDetailViewController-B3C32DC7B1BE4E38.o
duplicate symbol _OBJC_IVAR_$_MasterDetailMasterViewController._detailViewController in:
/Users/ilia3546/Library/Developer/Xcode/DerivedData/MasterDetail-fhgogwnbpzovbtaskgecptdnvgjs/Build/Intermediates/MasterDetail.build/Debug-iphonesimulator/MasterDetail.build/Objects-normal/i386/MasterDetailMasterViewController-A4C5EC1C14AE6E3A.o
duplicate symbol _OBJC_IVAR_$_MasterDetailMasterViewController._Controller1 in:
/Users/ilia3546/Library/Developer/Xcode/DerivedData/MasterDetail-fhgogwnbpzovbtaskgecptdnvgjs/Build/Intermediates/MasterDetail.build/Debug-iphonesimulator/MasterDetail.build/Objects-normal/i386/MasterDetailMasterViewController-A4C5EC1C14AE6E3A.o
duplicate symbol _OBJC_IVAR_$_MasterDetailMasterViewController.listOfDecide in:
/Users/ilia3546/Library/Developer/Xcode/DerivedData/MasterDetail-fhgogwnbpzovbtaskgecptdnvgjs/Build/Intermediates/MasterDetail.build/Debug-iphonesimulator/MasterDetail.build/Objects-normal/i386/MasterDetailMasterViewController-A4C5EC1C14AE6E3A.o
duplicate symbol _OBJC_IVAR_$_MasterDetailMasterViewController.listOfDecideOpis in:
/Users/ilia3546/Library/Developer/Xcode/DerivedData/MasterDetail-fhgogwnbpzovbtaskgecptdnvgjs/Build/Intermediates/MasterDetail.build/Debug-iphonesimulator/MasterDetail.build/Objects-normal/i386/MasterDetailMasterViewController-A4C5EC1C14AE6E3A.o
duplicate symbol _OBJC_IVAR_$_MasterDetailMasterViewController.listOfGraph in:
/Users/ilia3546/Library/Developer/Xcode/DerivedData/MasterDetail-fhgogwnbpzovbtaskgecptdnvgjs/Build/Intermediates/MasterDetail.build/Debug-iphonesimulator/MasterDetail.build/Objects-normal/i386/MasterDetailMasterViewController-A4C5EC1C14AE6E3A.o
duplicate symbol _OBJC_IVAR_$_MasterDetailMasterViewController.listOfGraphOpis in:
/Users/ilia3546/Library/Developer/Xcode/DerivedData/MasterDetail-fhgogwnbpzovbtaskgecptdnvgjs/Build/Intermediates/MasterDetail.build/Debug-iphonesimulator/MasterDetail.build/Objects-normal/i386/MasterDetailMasterViewController-A4C5EC1C14AE6E3A.o
duplicate symbol _OBJC_IVAR_$_MasterDetailMasterViewController.listOfAbout in:
/Users/ilia3546/Library/Developer/Xcode/DerivedData/MasterDetail-fhgogwnbpzovbtaskgecptdnvgjs/Build/Intermediates/MasterDetail.build/Debug-iphonesimulator/MasterDetail.build/Objects-normal/i386/MasterDetailMasterViewController-A4C5EC1C14AE6E3A.o
duplicate symbol _OBJC_IVAR_$_MasterDetailMasterViewController.listOfAboutOpis in:
/Users/ilia3546/Library/Developer/Xcode/DerivedData/MasterDetail-fhgogwnbpzovbtaskgecptdnvgjs/Build/Intermediates/MasterDetail.build/Debug-iphonesimulator/MasterDetail.build/Objects-normal/i386/MasterDetailMasterViewController-A4C5EC1C14AE6E3A.o
duplicate symbol _OBJC_CLASS_$_MasterDetailMasterViewController in:
/Users/ilia3546/Library/Developer/Xcode/DerivedData/MasterDetail-fhgogwnbpzovbtaskgecptdnvgjs/Build/Intermediates/MasterDetail.build/Debug-iphonesimulator/MasterDetail.build/Objects-normal/i386/MasterDetailMasterViewController-A4C5EC1C14AE6E3A.o
duplicate symbol _OBJC_METACLASS_$_MasterDetailMasterViewController in:
/Users/ilia3546/Library/Developer/Xcode/DerivedData/MasterDetail-fhgogwnbpzovbtaskgecptdnvgjs/Build/Intermediates/MasterDetail.build/Debug-iphonesimulator/MasterDetail.build/Objects-normal/i386/MasterDetailMasterViewController-A4C5EC1C14AE6E3A.o
ld: 23 duplicate symbols for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
appdelegate.m -
#import "MasterDetailAppDelegate.h"
#import "MasterDetailMasterViewController.h"
#import "MasterDetailDetailViewController.h"
#implementation MasterDetailAppDelegate
#synthesize window = _window;
#synthesize navigationController = _navigationController;
#synthesize splitViewController = _splitViewController;
- (void)dealloc
{
[_window release];
[_navigationController release];
[_splitViewController release];
[super dealloc];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
MasterDetailMasterViewController *masterViewController = [[[MasterDetailMasterViewController alloc] initWithNibName:#"MasterDetailMasterViewController_iPhone" bundle:nil] autorelease];
self.navigationController = [[[UINavigationController alloc] initWithRootViewController:masterViewController] autorelease];
self.window.rootViewController = self.navigationController;
} else {
MasterDetailMasterViewController *masterViewController = [[[MasterDetailMasterViewController alloc] initWithNibName:#"MasterDetailMasterViewController_iPad" bundle:nil] autorelease];
UINavigationController *masterNavigationController = [[[UINavigationController alloc] initWithRootViewController:masterViewController] autorelease];
MasterDetailDetailViewController *detailViewController = [[[MasterDetailDetailViewController alloc] initWithNibName:#"MasterDetailDetailViewController_iPad" bundle:nil] autorelease];
UINavigationController *detailNavigationController = [[[UINavigationController alloc] initWithRootViewController:detailViewController] autorelease];
self.splitViewController = [[[UISplitViewController alloc] init] autorelease];
self.splitViewController.delegate = detailViewController;
self.splitViewController.viewControllers = [NSArray arrayWithObjects:masterNavigationController, detailNavigationController, nil];
self.window.rootViewController = self.splitViewController;
}
[self.window makeKeyAndVisible];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
/*
Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
*/
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
/*
Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
*/
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
/*
Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
*/
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
/*
Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
*/
}
- (void)applicationWillTerminate:(UIApplication *)application
{
/*
Called when the application is about to terminate.
Save data if appropriate.
See also applicationDidEnterBackground:.
*/
}
#end
main.m -
//
// main.m
// MasterDetail
//
// Created by Wei-Meng Lee on 3/9/11.
// Copyright (c) 2011 __MyCompanyName__. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "MasterDetailAppDelegate.h"
int main(int argc, char *argv[])
{
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([MasterDetailAppDelegate class]));
}
}
I checked importing the .m file instead of the .h, but all correctly.
Check your import files, it may that you're importing a .m file.
#import "TimeModel.m"
In your build phases, check to see that you aren't compiling the same file more than once. i.e. If you search for main.m it should only return one result.
If that's not the problem, can you add the code from your main.m to the question?
Although the following is not the cause in the OP's case, it was mine, so I'll share it here for anyone facing the same error:
If you are getting a linker error on all global variables, you might need to add extern to their declarations in your header files.
Whether the lack of extern will generate this issue is dependent on build settings, more specifically on "No Common Blocks" under "Apple LLVM - Code Generation" (GCC_NO_COMMON_BLOCKS, -fno-common). If set to yes, which is the default in newer versions of Xcode, you'll get a linker error without extern.
Why extern?
The extern keywords makes it a declaration only (i.e. not also a definition), which since it's a header file is what you want. Some compilers allow it without extern and still 'do the right thing', but omitting extern is discouraged. Which is why newer versions of Xcode by default enable the warning.
Here is a situation in Xcode 7.0 with duplicate symbols error, in case anyone else comes across this scenario
.h file
NSUserDefaults *defaults; // <----placing this above the #interface caused the issue
#interface someViewController
//...
Change to
.h file
#interface someViewController
{
NSUserDefaults *defaults;
}
//...
This could happen also when you have the same #interface in different files with different implementations. For example you have a Player class, in the Player.h/m files and you have a Match class (Match.h/m), and a match is between two player, but not the aforementioned Player.
Player.h
#interface Player : NSObject
#property (nonatomic) NSUInteger _id;
#property (nonatomic, strong) NSString* firstName;
#property (nonatomic, strong) NSString* lastName;
#property (nonatomic, strong) NSString* username;
#end
Match.h
#class Player
#interface Match : NSObject
#property (nonatomic, strong) Player* player1;
#property (nonatomic, strong) Player* player2;
#property (nonatomic) NSUInteger matchId;
#end
#interface Player : NSObject
#property (nonatomic, strong) NSString* nickName;
#property (nonatomic, strong) NSString* point;
#property (nonatomic, strong) NSNumber* lastMove;
#end
In this case the the compiler see two different Player class implementation. You need to refactor the Player class in the Match.h file to MatchPlayer.
I ran into an issue where typedef was not added to an enum and the duplicate symbol error appeared between 2 files.
enum <name> {
...
} <name>;
By adding typedef before enum fixed the duplicate symbol.
In my case the problem was that .m file was included twice.
PROBLEM:
REASON:
SOLUTION: Leave only one file reference.
If this helps others, that was my case :
I wanted to declare 2 small classes in 1 header and implementation file.
Class 2 is using Class 1
When I got the error this was the situation:
header file - interface+implementation of class 1 , interface of class 2
Implementation file - implementation of class 2
After I moved the implementation of class 1 from header file to implementation file, there was no error and problem solved :
header file - interface of class 1 , interface of class 2
Implementation file - implementation of class 1, implementation of class 2
In my case, I had identical entity name and NSManagedObject names and failed to set the entity Class Codegen to "Manual/None" in the Data Model Inspector.

Linking problems with a category on Scripting Bridge

I am trying to write a category over iTunesTrack with associated objects (an NSMutableDictionary and an NSNumber)
#import "iTunes.h"
#import <objc/runtime.h>
#interface iTunesTrack (dictionary)
- (NSMutableDictionary*) getDictionary;
- (NSNumber*) getScan;
- (BOOL)scanTrack:(NSString *)equationString;
#end
This fails:
Undefined symbols for architecture x86_64:
"_OBJC_CLASS_$_iTunesTrack", referenced from:
l_OBJC_$_CATEGORY_iTunesTrack_$_dictionary in iTunesTrack+dictionary.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I have double checked that the Scripting Bridge framework is added and that the iTunesTrack+dictionary.m file is attached to the target. Could this be some error with combining Categories with Scripting Bridge?
Update:
If I replace iTunesTrack with SBObject, this works. I have no idea why, though.
Update 2:
This problem is reproducible:
Create new project
Add Scripting Bridge Framework and the iTunes.h header file.
Create new category of iTunesTrack with an arbitrary name
Ensure that iTunesTrack+name.h imports iTunes.h
Build
I found this page which describes using NSProxy and NSCache to store iTunesTrack objects. Would this be a better solution than trying to make a category?
Scripting Bridge is quite a mess.
The class iTunesTrack is actually called ITunesTrack under the hood.
I think they were not quite consistent with the leading lowercase i.
This is why they changed it after a while, but probably did not want to do it in the header file, to not change their API.
I don't think there is a way to fix this.
You can, however, just create the category on SBObject.
// The interface can be declared as iTunesTrack
#interface iTunesTrack (Additions)
...
#end
// The category MUST be implemented on SBObject
#implementation SBObject (Additions)
...
#end
Caution
Be aware that the category will be available on every SBObject, so make sure that all properties and methods have a unique interface.
You can't put a category on iTunesTrack (or ITunesTrack, or whatever it's called in your header) because that requires the class to exist at link time, and it doesn't: Scripting Bridge creates the target application's classes dynamically at runtime. (And they have technically arbitrary names, which is why -classForScriptingClass exists.) It's still possible to add a method to the generated class, but it means mucking about with the runtime, which is generally more trouble than it's worth. Just put your category method on SBObject and try to be careful.
NSAddict's answer pointed the way to do something I've always wanted: implementing debugQuickLookObject for SBObject types to make debugging easier. Here's the category that does iTunesTrack and iTunesArtwork.
// SBObject+Extensions.h
#import ScriptingBridge;
#interface SBObject (Extensions)
- (id)debugQuickLookObject;
#end
// SBObject+Extensions.m
#import "iTunes.h"
#implementation SBObject (Extensions)
- (id)debugQuickLookObject
{
NSString *className = self.className;
if ([className isEqualToString:#"ITunesTrack"])
{
return [self handleITunesTrack];
}
else if ([className isEqualToString:#"ITunesArtwork"])
{
return [self handleITunesArtwork];
}
return [self description];
}
- (NSString*)handleITunesTrack
{
iTunesTrack *track = (iTunesTrack *)self;
NSMutableString *s = [NSMutableString new];
[s appendFormat:#"Title: %#\n", track.name];
[s appendFormat:#"Artist: %#\n", track.artist];
[s appendFormat:#"Album: %#\n", track.album];
[s appendFormat:#"Duration: %f seconds\n", track.duration];
return s;
}
- (NSImage*)handleITunesArtwork
{
iTunesArtwork *artwork = (iTunesArtwork *)self;
NSData *data = [artwork rawData];
NSImage *image = [[NSImage alloc] initWithData:data];
return image;
}
#end
You may find the answer in this discussion:
linker command failed with exit code 1 (use -v to see invocation)
Also you can try to clean and then rebuild your project or go to Project -> Build Settings -> Valid Architectures and check whether there's all correct. Some of these advises may help you.

Pass information between classes

I'm fairly new to Objective-C and I'm running into a problem.
I need to pass some information from one viewcontroller to another. I've tried a number of methods and either get build error or don't make enough sense.
Here is what I have so far.
In the second view controllers h file:
#property (nonatomic) NSString *OwnerID;
The data should go into this property.
In the first view controllers m file:
MoreByUserViewController *moreimg =[[MoreByUserViewController alloc] init];
moreimg.OwnerID = ImageOener;
I think this isn't correct but don't know what else to write.
The clang error I get:
duplicate symbol _m_PageCounter in:
/Users/ianspence/Library/Developer/Xcode/DerivedData/Pickr-dohtanjxfozprjbuwlphjbhvxttm/Build/Intermediates/Pickr.build/Debug-iphonesimulator/Pickr.build/Objects-normal/i386/PKRViewController.o
/Users/ianspence/Library/Developer/Xcode/DerivedData/Pickr-dohtanjxfozprjbuwlphjbhvxttm/Build/Intermediates/Pickr.build/Debug-iphonesimulator/Pickr.build/Objects-normal/i386/MoreByUserViewController.o
ld: 1 duplicate symbol for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Is it a circular reference? check out your header files.
Your problem is something else, now you are getting error for _m_PageCounter. I think twice you put m_PageCounter or used same variable in two different headers..
in .h file just declare #class MoreByUserViewController. and add header file of MoreByUserViewController in .m fie.
#interface MoreByUserViewController : UIViewController
{
NSString *mOwnerID;
}
#property(nonatomic, retain) NSString *OwnerID;
-(id)initWithID:(NSString*)inId;
#end
#implementation MoreByUserViewController
#synthesize OwnerID = mOwnerID;
-(id)initWithID:(NSString*)inId
{
if(self = [super init])
{
self.OwnerID = inId;
}
return self;
}
#end
//Somewhere else in code
MoreByUserViewController *moreimg =[[MoreByUserViewController alloc] initWithID:#"AnyIdOnUrWish"];
duplicate symbol _m_PageCounter means you have a constant or variable or function named m_PageCounter defined in two places. Specifically, in PKRViewController.m and MoreByUserViewController.m.
Your options:
Delete one of them.
Rename one of them.
Declare one of them static so they won't be visible outside of that source file.