如何在 Xcode 6.3 中检查 Facebook 帐户支持?
How to check for Facebook account support in Xcode 6.3?
在我的 Facebook 模型 class 中,我有一个功能来检查用户的 iOS 是否支持 Facebook 帐户管理:
+ (BOOL)canUseExternalNetwork
{
return &ACAccountTypeIdentifierFacebook != nil;
}
从 Xcode 6.3 开始,编译器报错:
Comparison of address ACAccountTypeIdentifierFacebook not equal to
null pointer is always true
首先,我不明白为什么旧的 iOS 上的未定义常量会解析为大于 0 的地址。更重要的是,我想解决这个问题而不用破解:
- 我不想更改编译器设置来关闭此警告。所要做的就是使我的代码 运行,但不正确 运行。
- 我不想使用 iOS 版本检查。当 Facebook 不再受支持时,这样做可能会在未来中断。我认为 Facebook 已经停止在其新的 Graph API 2.0 中使用本机登录支持。新的 SDK 不再使用 OS 提供的登录弹出窗口。相反,它会跳转到 Facebook 应用程序。
- 适用于任何类型常量的通用解决方案会很好。虽然我现在只需要为 Facebook(和 Twitter)解决它,但我仍然想学习如何处理未来类似的情况。
This has all the hallmarks of a slight misfeature (also known as a bug) in the compiler that it doesn't properly assess -weak_framework
when using symbols defined in framework headers as being weakly linked, and as such considers the code a no-op.
这意味着优化器很高兴能够从代码中删除 if 检查 - 当我使用一段简单的测试代码时它确实这样做了。
#import <Accounts/ACAccountType.h>
#import <stdio.h>
int
main(int argc, char **argv)
{
if (&ACAccountTypeIdentifierFacebook != NULL)
NSLog(@"Hello\n");
return (0);
}
此代码编译为:
$ clang -weak_framework Accounts -framework Foundation weak.m
weak.m:8:10: warning: comparison of address of 'ACAccountTypeIdentifierFacebook' not equal to a null pointer is always true [-Wtautological-pointer-compare]
if (&ACAccountTypeIdentifierFacebook != NULL)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~
1 warning generated.
检查时,显示代码中甚至没有引用 ACAccountTypeIdentifierFacebook
符号:
$ nm -m a.out
(undefined) external _NSLog (from Foundation)
(undefined) external ___CFConstantStringClassReference (from CoreFoundation)
0000000100000000 (__TEXT,__text) [referenced dynamically] external __mh_execute_header
0000000100000f40 (__TEXT,__text) external _main
(undefined) external dyld_stub_binder (from libSystem)
即优化器将其完全删除。您可以使用 otool -tv a.out
检查结果代码,您会看到 if 测试被完全跳过。
希望它会在编译器的未来版本中得到修复,但是您可以暂时解决该问题。
为了让编译器认为该符号是弱的,它需要显式标记为 weak import,这意味着它需要看起来像:
extern NSString * const ACAccountTypeIdentifierFacebook __attribute__((weak_import));
这意味着代码如下:
if (&ACAccountTypeIdentifierFacebook != NULL) {
NSLog(@"Have Facebook");
}
然后将正常工作。如果我们在示例代码的开头添加这样一行并编译它,我们会看到它编译没有问题,并且该符号出现在 nm -m a.out
的输出中,并且 if 测试是出现在 otool -tv a.out
.
的结果输出中
在我的 Facebook 模型 class 中,我有一个功能来检查用户的 iOS 是否支持 Facebook 帐户管理:
+ (BOOL)canUseExternalNetwork
{
return &ACAccountTypeIdentifierFacebook != nil;
}
从 Xcode 6.3 开始,编译器报错:
Comparison of address ACAccountTypeIdentifierFacebook not equal to null pointer is always true
首先,我不明白为什么旧的 iOS 上的未定义常量会解析为大于 0 的地址。更重要的是,我想解决这个问题而不用破解:
- 我不想更改编译器设置来关闭此警告。所要做的就是使我的代码 运行,但不正确 运行。
- 我不想使用 iOS 版本检查。当 Facebook 不再受支持时,这样做可能会在未来中断。我认为 Facebook 已经停止在其新的 Graph API 2.0 中使用本机登录支持。新的 SDK 不再使用 OS 提供的登录弹出窗口。相反,它会跳转到 Facebook 应用程序。
- 适用于任何类型常量的通用解决方案会很好。虽然我现在只需要为 Facebook(和 Twitter)解决它,但我仍然想学习如何处理未来类似的情况。
This has all the hallmarks of a slight misfeature (also known as a bug) in the compiler that it doesn't properly assess
-weak_framework
when using symbols defined in framework headers as being weakly linked, and as such considers the code a no-op.
这意味着优化器很高兴能够从代码中删除 if 检查 - 当我使用一段简单的测试代码时它确实这样做了。
#import <Accounts/ACAccountType.h>
#import <stdio.h>
int
main(int argc, char **argv)
{
if (&ACAccountTypeIdentifierFacebook != NULL)
NSLog(@"Hello\n");
return (0);
}
此代码编译为:
$ clang -weak_framework Accounts -framework Foundation weak.m
weak.m:8:10: warning: comparison of address of 'ACAccountTypeIdentifierFacebook' not equal to a null pointer is always true [-Wtautological-pointer-compare]
if (&ACAccountTypeIdentifierFacebook != NULL)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~
1 warning generated.
检查时,显示代码中甚至没有引用 ACAccountTypeIdentifierFacebook
符号:
$ nm -m a.out
(undefined) external _NSLog (from Foundation)
(undefined) external ___CFConstantStringClassReference (from CoreFoundation)
0000000100000000 (__TEXT,__text) [referenced dynamically] external __mh_execute_header
0000000100000f40 (__TEXT,__text) external _main
(undefined) external dyld_stub_binder (from libSystem)
即优化器将其完全删除。您可以使用 otool -tv a.out
检查结果代码,您会看到 if 测试被完全跳过。
希望它会在编译器的未来版本中得到修复,但是您可以暂时解决该问题。
为了让编译器认为该符号是弱的,它需要显式标记为 weak import,这意味着它需要看起来像:
extern NSString * const ACAccountTypeIdentifierFacebook __attribute__((weak_import));
这意味着代码如下:
if (&ACAccountTypeIdentifierFacebook != NULL) {
NSLog(@"Have Facebook");
}
然后将正常工作。如果我们在示例代码的开头添加这样一行并编译它,我们会看到它编译没有问题,并且该符号出现在 nm -m a.out
的输出中,并且 if 测试是出现在 otool -tv a.out
.