【问题标题】:Cocoa check if function existsCocoa 检查函数是否存在
【发布时间】:2013-06-19 13:51:36
【问题描述】:

我想使用仅在 OS X 10.9 上可用但不使用 10.9 SDK 编译的函数。这可能吗?

我已经尝试过弱链接,但是编译器只是给出一个函数未定义的错误。

【问题讨论】:

  • 等待 - 这是一个函数还是一个方法。两者非常不同。
  • 这是一个 C 函数 (AXIsProcessTrustedWithOptions),仅在 10.9 上可用。

标签: objective-c xcode macos cocoa


【解决方案1】:

您说您不想针对 10.9 进行编译,但没有给出任何理由。以防万一您可以

如果您将目标设置为 10.9 并且您的部署设置为更低,那么 Xcode 将弱链接 10.9 框架。然后,您可以通过将其名称与NULL 进行比较来测试可用的 C 函数。此片段取自this document

extern int MyWeakLinkedFunction() __attribute__((weak_import));

int main()
{
   int result = 0;

   if (MyWeakLinkedFunction != NULL)
   {
      result = MyWeakLinkedFunction();
   }

   return result;
}

(顺便说一句:这种方式没有沙箱问题。)

【讨论】:

  • 很棒的评论,在 2020 年仍然适用于 Swift 中使用的桥接头 :)
【解决方案2】:

假设您正在谈论一个 C 函数,您可以使用 dlopen 函数来做到这一点:

#include <dlfcn.h>

int main() {
    void *lib = dlopen("/System/Library/Frameworks/ApplicationServices.framework/ApplicationServices", RTLD_LAZY);
    void *function = dlsym(lib, "CGColorGetConstantColor");

    // cast the function to the right format
    CGColorRef (*dynamic_getConstantColor)(CFStringRef colorName) = function;

    NSLog(@"%@", dynamic_getConstantColor(CFSTR("kCGColorBlack")));

    dlclose(lib);
}

输出:

2013-06-20 12:43:13.510 TestProj[1699:303] [(kCGColorSpaceICCBased;kCGColorSpaceModelMonochrome;通用灰色配置文件)](0 1)

不过,您首先需要弄清楚您想要的函数所在的 dylib。

打破 iOS 和 Mac 上的沙盒限制。这是您试图绕过链接器所付出的代价。

【讨论】:

  • 知道在哪里可以找到 /System/Library/Frameworks/ApplicationServices.framework/Versions/Current/Frame‌​works/HIServices.framework/Versions/Current/HIServices 的 dylib 吗?
  • @bogdansrc 是的,用框架中的符号更新了我的答案。
  • 输出“Hello World,来自动态!”不再与代码一致,这可能会使未来的读者感到困惑:-)
【解决方案3】:

如果您正在处理 Objective-C 方法,也许您可​​以使用选择器来完成。 所以首先检查选择器是否可用:

[object respondsToSelector:@selector(osxMavericksFun)]

如果此测试正确,请尝试通过选择器触发方法

[object performSelector:@selector(osxMavericksFun)];

如果你想调用 c 函数,这是没有办法的。

【讨论】:

  • 这个问题是关于函数,而不是方法。
  • 那么,如果它可用,您究竟想调用什么?
  • 没有办法做到这一点。您需要在 10.9 上构建才能使用 10.9 的 c 函数
  • @lukaswelte 实际上,如果您愿意,可以使用 dlopen/dlsym 来做到这一点。
  • 这不会破坏 OS X 沙盒的限制吗?
【解决方案4】:

你应该这样做

if (AXIsProcessTrustedWithOptions != NULL){
    NSDictionary *options = @{(__bridge id)kAXTrustedCheckOptionPrompt: @YES};
    accessibilityEnabled = AXIsProcessTrustedWithOptions((__bridge CFDictionaryRef)options);
}else{
    accessibilityEnabled = AXIsProcessTrusted();
}

apple's documentation Listing 3-2 中描述了此方法。它比您认为正确的 Richard J. Ross III 描述的方法要简单得多。

【讨论】:

    猜你喜欢
    • 2012-11-22
    • 1970-01-01
    • 1970-01-01
    • 2018-05-22
    • 2011-10-23
    • 2010-11-10
    • 2014-02-18
    • 2015-07-24
    • 1970-01-01
    相关资源
    最近更新 更多