根据this回答,我正在尝试声明和定义全局变量并收到此错误:
Undefined symbols for architecture armv7: "_loggedIn", referenced from: -[XYZAppDelegate application:didFinishLaunchingWithOptions:] in XYZAppDelegate.o -[XYZFolderViewController viewDidAppear:] in XYZFolderViewController.o -[XYZFolderViewController loginViewController:didEnterUsername:password:] in XYZFolderViewController.o ld: symbol(s) not found for architecture armv7 clang: error: linker command failed with exit code 1 (use -v to see invocation)
我在这里找到了很多答案,但所有答案都指的是不同的问题(尽我所能)。
... extern BOOL loggedIn; ...
... @implementation XYZAppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { loggedIn = 0; ... } ...
... extern BOOL loggedIn; ...
... @implementation ... - (void)loginViewController:(XYZLoginViewController *)loginViewController didEnterUsername:(NSString *)username password:(NSString *)password { ... if ([username isEqualToString:theUsername] && [password isEqualToString:thePassword]) { loggedIn = 1; /* 0 == not logged in. 1 == logged in. */ ... } ... }
此全局变量的一点是保存有关用户登录(或不登录)的信息。
我知道在Objective-C中使用extern
并不是一种干净的方法。但是,除extern
使用外,我还会欣赏其他类型解决方案的提示。
期待这是一个新秀问题。
答案 0 :(得分:4)
extern
表示:“此事已在其他地方定义”
所以,你没有声明一个全局变量。你只是说别人是,而你想要使用它。因此,当编译器试图找到它并且显示为空白时,它会告诉您它无法找到定义。
并非你应该尝试使用全局,你不应该这样做,但是可以使用static
来完成。
您应该使loggedIn
标志成为实例变量,并提供对该值的正确,只读访问。这意味着公开阅读,但私下可写。因此只能在类内部更改状态(作为loginViewController:...
)的结果。
所以,在.h文件中你会得到:
@property (assign, nonatomic, readonly) BOOL loggedIn;
然后在.m文件中:
@property (assign, nonatomic, readwrite) BOOL loggedIn;
答案 1 :(得分:1)
在您的应用中全局提供状态通常不是一个好主意。您应该始终尽量将可变状态保持在最低限度。接受这个read或查看Functional Programming Priciples Course这些非常好,可以帮助您开始成为更好的程序员。
extern
关键字最适合在任何地方提供常量对象。例如。 NSString的。像这样:
Constants.h
extern NSString* kAKeyPath;
extern double kPI;
Constants.m
NSString * const kAStringContant = @"contact.name";
const double kPI = 3.14159265359;
以这种方式使用值是有利的,因为编译器可以为您检查它(它不仅仅是您需要记住的字符串或int值)并且它将存储在程序数据存储中的一个实例中(与存储它相比)如果不使用extern
,它们会出现多次。
答案 2 :(得分:0)
一个问题可能是如果你有多个目标,你已经导入.h文件,其中包含一个存在变量的承诺,但是你没有包含.c或.m,所以你错过了编译单元符号。当然,您可以设法在没有多个目标的情况下进入此状态,但由于Xcode会自动将.m添加到默认目标,因此您通常不会进入该状态。