在使用extern使变量全局变量时获取“架构armv7的未定义符号”

时间:2013-07-04 20:01:47

标签: ios objective-c

根据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)

我在这里找到了很多答案,但所有答案都指的是不同的问题(尽我所能)。

XYZAppDelegate.h

...
extern BOOL loggedIn;
...

XYZAppDelegate.m:

...
@implementation XYZAppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    loggedIn = 0;
    ...
}
...

XYZFolderViewController.h

...
extern BOOL loggedIn;
...

XYZFolderViewController.m

...
@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使用外,我还会欣赏其他类型解决方案的提示。 期待这是一个新秀问题。

3 个答案:

答案 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添加到默认目标,因此您通常不会进入该状态。