如何在Swift中进行弱链接?

时间:2014-07-06 01:32:06

标签: ios objective-c linker swift dynamic-linking

在Objective-C中,如果我想使用仅出现在新版iOS中的特定类,我会这样做:

if( [UIBlurEffect class] ) {
  // do something with UIBlurEffect
}
else {
  // gracefully fallback to old behavior
}

然而,等效的Swift:

if UIBlurEffect.self != nil {
  let blur: UIBlurEffect = UIBlurEffect(...)
  // ...
else {
  // ...
}

// also occurs with NSClassFromString("UIBlurEffect")

没有相同的功能。

如果在NSNewFeature可用的环境中运行,一切都很好。但是如果未定义类,则在启动应用程序时会出现链接错误:

dyld: Symbol not found: _OBJC_CLASS_$_UIBlurEffect

那么如何在Swift中进行弱链接?

修改已添加UIBlurEffect作为具体示例。

2 个答案:

答案 0 :(得分:5)

好像我已经知道你能做什么

  1. 我使用NSClassFromString()检查设备上是否有类,即

    if NSClassFromString("UIBlurEffect") {
        let blur = UIBlurEffect(...)
        //...
    }
    else {
        //...
    }
    
  2. 需要使UIKit.framework(或其他相应的框架)可选。如果您在XCode6-BetaX中创建基于Swift的应用程序,则所有框架都不会明确添加到链接构建阶段,因此您需要转到目标设置,将UIKit.framework添加为链接框架(在'将二进制文件链接到库'部分)并将其状态更改为Optional此步骤可以解决这个问题,并且我设法运行特定于版本的代码而没有任何问题。

  3. 更新:由于Xcode 6 beta 6(来自@ user102008),您不再需要将其设为可选项

    更新2 :您无法对nil执行隐式if语句检查(自Xcode 6 Beta 5起)。你需要这样断言:

        if NSClassFromString("UIBlurEffect") != nil {
            let blur = UIBlurEffect(...)
            //...
        }
        else {
            //...
        }
    

    (来自@ daniel-galasko)

答案 1 :(得分:2)

在我将测试人员分发给我们的测试人员之后,我最后使用这一点来加上我的两分钱。 Swift编译器中存在一个错误(Xcode< = 6.1.1),当在Release模式下构建时,编译器在调用NSClassFromString时实际上没有返回nil。

要检查我,只需将配置更改为发布,然后查看她是如何崩溃的。

我最终必须在其他地方显式检查iOS版本或简单的respondsToSelector调用。

所以我的代码看起来像这样:

    if NSClassFromString("UIVisualEffectView") != nil {
        //use the blur safely
    } else {
        //abandon blur! try something safer
    }

我最终不得不使用它

switch UIDevice.currentDevice().systemVersion.compare("8.0.0", options: NSStringCompareOptions.NumericSearch) {
        case .OrderedSame, .OrderedDescending:
            //go wild with blur
        case .OrderedAscending:
            //blur shall not pass here!
        }

这个问题涉及同一个问题 - UIAlertView is crashing app on iOS 7