【问题标题】:How do I do weak linking in Swift?如何在 Swift 中进行弱链接?
【发布时间】:2014-08-26 20:02:43
【问题描述】:

在 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 作为具体示例。

【问题讨论】:

  • 我猜你应该使用可选的,比如 if let featureAvailable = NSNewFeature? {} 别的 {} 。但我对 swift 很陌生
  • 对不起 NSNewFeature.self
  • @user102008 不是骗子——我想有条件地使用单个类
  • 不应该是 [NSNewFeature class] 而不是 [NSNewFeatureClass class] 吗?或尝试其他语法: Class cls = NSClassFromString (@"NSRegularExpression"); if (cls) { // 创建一个类的实例并使用它。 } else { // 当类不可用时要遵循的备用代码路径。 }

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


【解决方案1】:

看来我已经知道你能做什么了

  1. 我使用NSClassFromString() 来检查设备上是否有可用的课程,即

    if NSClassFromString("UIBlurEffect") {
        let blur = UIBlurEffect(...)
        //...
    }
    else {
        //...
    }
    
  2. 需要将UIKit.framework(或其他相应的框架)设为可选。如果您在 XCode6-BetaX 中创建基于 Swift 的应用程序,所有框架都不会显式添加到链接构建阶段,因此您需要转到您的目标设置,添加 UIKit.framework 作为链接框架(在 'Link Binary With图书馆的部分)并将其状态更改为Optional这一步成功了,我已经成功地运行了特定于版本的代码。

更新:您不再需要将其设为可选,因为 Xcode 6 beta 6(通过 @user102008)

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

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

(来自@daniel-galasko)

【讨论】:

  • import 语句的全部意义在于避免手动添加框架的需要
  • 我认为这可能只是一个实现错误。或功能。
  • 更新:在 Xcode 6 beta 6 中,您不再需要将其设为可选
  • 您实际上不能执行隐式 if 语句检查 nil。你需要断言 if NSClass... != nil {use that class} else {use something else}
【解决方案2】:

只是为了增加我的两分钱,因为我最终在将应用程序分发给我们的测试人员时立即感到沮丧。 Swift 编译器 (Xcode NSClassFromString 时实际上不会返回 nil。

要检查我,只需将您的配置更改为 Release,看看她是如何崩溃的。

我最终不得不在其他地方明确检查 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

【讨论】:

  • 有趣 - 在 6.3 测试版中还会发生这种情况吗?
  • @Bill 稍后会确认是否是这种情况,我希望不会,因为他们提到他们修复了发布优化的几个问题
猜你喜欢
  • 2014-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-22
  • 2011-02-07
  • 1970-01-01
相关资源
最近更新 更多