【问题标题】:How to check for Facebook account support in Xcode 6.3?如何在 Xcode 6.3 中检查 Facebook 帐户支持?
【发布时间】:2015-04-18 15:17:21
【问题描述】:

在我的 Facebook 模型类中,我有一个函数来检查用户的 iOS 是否支持 Facebook 帐户管理:

+ (BOOL)canUseExternalNetwork
{
    return &ACAccountTypeIdentifierFacebook != nil;
}

从 Xcode 6.3 开始,编译器给出错误提示:

比较地址 ACAccountTypeIdentifierFacebook 不等于 空指针始终为真

首先,我不明白为什么旧 iOS 上的未定义常量会解析为大于 0 的地址。更重要的是,我想在没有 hack 的情况下解决这个问题:

  • 我不想更改编译器设置来关闭此警告。所做的只是让我的代码运行,但运行不正确。
  • 我不想使用 iOS 版本检查。当 Facebook 不再受支持时,这样做可能会在未来中断。我认为 Facebook 已经停止在其新的 Graph API 2.0 中使用本机登录支持。新的 SDK 不再使用操作系统提供的弹出窗口进行登录。相反,它会跳转到 Facebook 应用。
  • 适用于任何类型常量的通用解决方案会很好。虽然我现在只需要为 Facebook(和 Twitter)解决它,但我仍然想学习如何在未来处理类似的情况。

【问题讨论】:

    标签: objective-c xcode cocoa-touch xcode6


    【解决方案1】:

    这具有编译器中轻微错误功能(也称为错误)的所有特征,即当使用框架头文件中定义为弱链接的符号时,它无法正确评估-weak_framework,因此认为代码无操作。

    这意味着优化器很高兴能够从代码中删除 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 的结果输出。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-13
      • 2020-05-11
      • 2014-09-12
      • 1970-01-01
      • 2011-06-30
      • 1970-01-01
      相关资源
      最近更新 更多