在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
作为具体示例。
答案 0 :(得分:5)
好像我已经知道你能做什么
我使用NSClassFromString()
检查设备上是否有类,即
if NSClassFromString("UIBlurEffect") {
let blur = UIBlurEffect(...)
//...
}
else {
//...
}
需要使UIKit.framework
(或其他相应的框架)可选。如果您在XCode6-BetaX中创建基于Swift的应用程序,则所有框架都不会明确添加到链接构建阶段,因此您需要转到目标设置,将UIKit.framework
添加为链接框架(在'将二进制文件链接到库'部分)并将其状态更改为Optional
。 此步骤可以解决这个问题,并且我设法运行特定于版本的代码而没有任何问题。
更新:由于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