Linker error for global variable [duplicate] - objective-c

This question already has answers here:
Accesing global variable giving linker error in objective C
(2 answers)
Closed 9 years ago.
I'm making a small, simple application, so I decided to use global variables over Singletons. I'm also only using one.
My app pulls an int from a small preference file, and that is set to the global variable as an NSInteger. The global variable may be changed while the app is running.
AppController.h
#import <Cocoa/Cocoa.h>
extern NSInteger preferenceNumber;
#interface ....
App Controller.m
-(void)someMethod {
...
//fileContents is a string containing the int that is inside the file
preferenceNumber = [fileContents intValue]
...
}
The Linker Errors (2):
Undefined symbols for architecture x86_64:
"_preferenceNumber", referenced from:
-[AppController someMethod1] in AppController.o
-[AppController someMethod2:] in AppController.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
The bolded parts are the two errors.
What is causing this? What is the simplest, best way to solve it?

Just add one line in your implementation class:-
AppContollr.m
#implementation AppContoller
NSInteger preferenceNumber;

Related

error: declaration of instance variables in the interface is deprecated [-Werror,-Wobjc-interface-ivars]

I just cloned a project from github and I went to build it and I ran into this error over and over again. Any idea what the problem is?
Here is some of my error output and some of the code that causes the error:
NOTE:
_indexSetFlags and _internal are the variables that are causing the error in this code example
#import <Foundation/NSObject.h>
#import <Foundation/NSRange.h>
NS_ASSUME_NONNULL_BEGIN
#interface NSIndexSet : NSObject <NSCopying, NSMutableCopying, NSSecureCoding> {
#protected // all instance variables are private
struct {
NSUInteger _isEmpty:1;
NSUInteger _hasSingleRange:1;
NSUInteger _cacheValid:1;
NSUInteger _reservedArrayBinderController:29;
} _indexSetFlags;
union {
struct {
NSRange _range;
} _singleRange;
struct {
void * _data;
void *_reserved;
} _multipleRanges;
} _internal;
}
ERROR OUTPUT:
/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSAutoreleasePool.h:14:11:
error: declaration of instance variables in the
interface is deprecated [-Werror,-Wobjc-interface-ivars]
void *_reserved2;
/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSString.h:543:9:
error: declaration of instance variables in the interface is
deprecated [-Werror,-Wobjc-interface-ivars]
int numBytes;
^ /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSString.h:545:9:
error: declaration of instance variables in the interface is
deprecated [-Werror,-Wobjc-interface-ivars]
int _unused;
^
/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSNotification.h:39:11:
error: declaration of instance variables in the
interface is deprecated [-Werror,-Wobjc-interface-ivars]
void *_impl;
^
fatal error: too many errors emitted, stopping now [-ferror-limit=] 20
errors generated.
The following build commands failed: CompileC
/Users/bananaman123/Desktop/eecs481/hw6/wz_build/lib/sdl/warzone2100.build/Debug/sdl-backend.build/Objects-normal/x86_64/cocoa_wz_menus.o lib/sdl/cocoa_wz_menus.mm normal x86_64 objective-c++
com.apple.compilers.llvm.clang.1_0.compiler (1 failure)
I left out a lot of the error output, but all of the error messages contain "error: declaration of instance variables in the interface is deprecated [-Werror,-Wobjc-interface-ivars]"
As the repository README.md suggests at the very last line, go and read
https://github.com/Warzone2100/warzone2100/blob/master/macosx/README.md
then go step by step and fulfil the requirements.
It's mainly written in C++ and so it needs according treatment.
You need CMake 3.15+,
find it here https://cmake.org/download/#latest
also Gettext via Homebrew
and Asciidoctor via Homebrew as well.
As you obviously use OSX 10.15+ you don't need GCC, Xcode > 11 is fine.
Your errors go back to a bogus project setup.
NSIndexSet is a class that belongs to Foundation Framework. Usually nothing to repair for you in this code. Quite sure this comes up because Objective-C++ is assumed to work which is a simple way to include C++ into your Xcode project. Read more about working with .mm files if you want to change the way it is added to your project because..
Somewhere between the lines in the Readme.md is also written..
"Run CMake to generate the Xcode project"

Invalid token at start of a preprocessor expression Xcode [duplicate]

This question already has an answer here:
Macro in Objective-C calling isEqualToString: produces error about invalid token
(1 answer)
Closed 6 years ago.
#define A7VERSION() ({[[[[[UIDevice currentDevice] systemVersion] componentsSeparatedByString:#"."] objectAtIndex:0] intValue];})
#define IS_OS_7 A7VERSION()>=7
The above declaration seems to compile well.
But as soon as I add it a .m file I get the following exception "invalid token at start of a preprocessor expression". I am not able to understand where I could be wrong
#implementation AppViewController
#if IS_OS_7
….
#else
….
#endif
#end
The problem has nothing to do with iOS 7.
Your #define does not lead to something that can be resolved at compile time. An #ifdef only works if the conditional is something that can be determined at compile time. It cannot be used to change behavior at runtime based on the environment an app is running on.

I am having all the time this issue after running my app

I don't know why, but after a while working without problems I added some buttons, then I launched my app and this error appeared:
ld: duplicate symbol _x in
/Users/alexbarco/Library/Developer/Xcode/DerivedData/RecolectaDatos-ayjpqqcajbhuzvbkvernzsyunpbe/Build/Intermediates/RecolectaDatos.build/Debug-iphonesimulator/RecolectaDatos.build/Objects-normal/i386/SeconViewController.o
and
/Users/alexbarco/Library/Developer/Xcode/DerivedData/RecolectaDatos-ayjpqqcajbhuzvbkvernzsyunpbe/Build/Intermediates/RecolectaDatos.build/Debug-iphonesimulator/RecolectaDatos.build/Objects-normal/i386/ViewController.o
for architecture i386 clang: error: linker command failed with exit
code 1 (use -v to see invocation)
Whenever I have duplicate symbol errors, it is almost always because I have a circular #import in my headers. The solution is quite simple, use forward declarations where possible, and #import .h files from .m files instead.
There are just two cases where you need to #import one .h from another:
if you are extending the class in the #import
you are implementing a protocol in the #import
Specifically, you do not need to import files just to use a class name or protocol in your signatures; instead use forward declarations.
For example, this (in Bar.h):
#import "Foo.h"
might become this (Bar.h):
#class Foo;
#protocol FooDelegate;
and bar.m:
#import "Foo.h"
Here is a link to the documentation on forward declarations.
The "duplicate symbol" message means that you're declaring some name (in this case, _x) twice in the same scope. Say you had code like this:
int _x = 1;
int _x = 2;
You'd expect to get an error then, right? You can use the same name for two things at the same time.
The error you're getting is essentially the same. You're declaring _x somewhere, and from the compiler's point of view you're doing it twice. There are a few ways to deal with this, depending on what _x represents.
chrahey's answer explains about forward class declarations. I won't cover that again here except to say that a forward declaration helps you resolve circular references, where the definition of class A depends on class B and vice versa.
If _x is a variable, it's likely that you're trying to declare it in a header file. The compiler basically copies the contents of each header file that you import into the source file, so if you declare a variable in a header file and then import that header into two or more implementation files, you'll end up with multiple declarations of that variable. To get around that, use the extern keyword to tell the compiler "this name will be declared somewhere else" and then put the real declaration in an implementation file:
Foo.h:
extern int _x;
Foo.m
int _x;
Pretty much the same thing goes for functions. It doesn't appear that _x is a function, but if it were, and if you were silly enough to put the function definition in a header file, then you'd again get an error if that file were imported into more than one implementation file. This is why header files contain prototypes, not definitions:
Foo.h:
int foo(int a);
Foo.m
int foo(int a)
{
return a + 10;
}

Linker error on const values

I am trying to create some string constants so I have the following:
Constants.h
extern NSString* const CONSTANT_ONE;
Constants.m
NSString *const CONSTANT_ONE = #"CONSTANT_ONE";
SomeOtherFile.m
#import "Constants.h"
... snip
NSString* something = CONSTANT_ONE;
Constants.m is listed in the "Compile Sources" bit of the target's build phases and is a member of the target when I look in its "Target Membership" section of the sidebar.
When I try to compile I get an error like:
Undefined symbols for architecture i386:
"_CONSTANT_ONE", referenced from:
-[SomeOtherFile someMethod:] in SomeOtherFile.o
I think I might be misunderstanding something basic here - can anyone help me with this error please?
The code in my initial question was correct. I don't know why but simply closing and re-opening Xcode solved the problem and it built fine. Just Xcode getting itself confused.

extern in objective-C; do they behave differently than C?

I required to share a const value between two files; so rather than keeping a magical number I decided to use a const variable.
So I created a global variable const int viewTag = 100; in my appDelegate.m
Then accessed it as extern const int viewTag; but I got following linker error:
Undefined symbols for architecture i386:
"viewTag", referenced from:
-[xxxViewController launchxxx] in libxxx_iPad.a(xxxViewController.o)
ld: symbol(s) not found for architecture i386
collect2: ld returned 1 exit status
But the above thing is perfectly leagal in normal C,C++ env. can anybody throw some light?
Update: putting extern const int viewTag; in header and importing that header works, but I really don't want to do that for a single const int
Try putting:
extern const int viewTag;
in appDelegate.h, then importing this header where you need access to viewTag.
Another way is to use #define viewTag 100 in .pch file.
But I think, the best way is to create .h file with constants and include where you want