【问题标题】:Array element cannot be bridged to Objective-C数组元素无法桥接到 Objective-C
【发布时间】:2014-06-09 03:38:07
【问题描述】:

我有这段代码可以创建一个视图并对其应用渐变。

import UIKit
import QuartzCore


let rect : CGRect = CGRectMake(0,0,320,100)

var vista : UIView = UIView(frame: rect)

let gradient : CAGradientLayer = CAGradientLayer()
gradient.frame = vista.bounds

let cor1 = UIColor.blackColor()
let cor2 = UIColor.whiteColor()

let arrayColors = [cor1.CGColor, cor2.CGColor]

gradient.colors = arrayColors

view.layer.insertSublayer(gradient, atIndex:0)

Xcode 没有给我编译错误,但代码在行上崩溃了

let arrayColors = [cor1.CGColor, cor2.CGColor]

带有消息数组元素无法桥接到Objective-C

事实上,我预计它会在那里崩溃,因为我不确定如何在 Swift 上创建一个 CGColors 数组。这里令人惊讶的是 Xcode 提到了 Objective-C。在我看来,我正在快速创建一个 CGColorRef ...

有什么线索吗?为什么要提到 Objective-C,我该如何解决?

【问题讨论】:

标签: swift


【解决方案1】:

之所以提到 Objective-C,是因为 UIKit 和 QuartzCore 是 Objective-C 框架。特别是,gradient.colors = arrayColors 正在调用一个期望 NSArray 的 Objective-C 方法。

这似乎是一个错误,因为 Apple 的文档表明该数组应该自动桥接到 NSArray,只要数组中的项目可以被视为 AnyObject

当你从一个 Swift 数组桥接到一个 NSArray 对象时,元素 在 Swift 数组中必须与 AnyObject 兼容。例如,一个斯威夫特 Int[] 类型的数组包含 Int 结构元素。 Int 类型是 不是类的实例,而是因为 Int 类型桥接到 NSNumber 类,Int 类型与 AnyObject 兼容。因此,你 可以将 Int[] 类型的 Swift 数组桥接到 NSArray 对象。如果 Swift 数组中的元素与 AnyObject 不兼容,运行时错误 当你桥接到一个 NSArray 对象时发生。

您也可以按照上面列出的相同桥接规则,直接从 Swift 数组字面量创建 NSArray 对象。当你 显式键入常量或变量作为 NSArray 对象并赋值 它是一个数组字面量,Swift 创建一个 NSArray 对象而不是 Swift 数组。

目前,解决方法是将arrayColors 声明为NSArray

let arrayColors: NSArray = [cor1.CGColor, cor2.CGColor]

或者声明为服用AnyObject

let arrayColors: Array <AnyObject> = [cor1.CGColor, cor2.CGColor]

【讨论】:

  • 啊,我明白了。我不明白第二行代码。你在那里说什么?让我成为一个数组,其中每个元素都是 ?但这不是默认行为?
  • 默认行为是数组项是您放入数组中的任何内容。例如只有字符串、整数等。在这种情况下,它只需要CGColorRef,这是CGColor 方法返回的内容。 AnyObject 可以是任何类型的混合,只要它们与 AnyObject 兼容,而不是单一类型。由于桥接需要能够将数组类型移动到 AnyObject,因此从一开始就这样声明它可以让我们解决 Objective-C 桥接问题。
  • 是的,Swift 有很多东西需要吸收,而且在接下来的几个月里它会不断发展。我猜Objective-C桥暂时会有很多陷阱......我建议通过创建一个可变的字符串数组然后尝试添加一个整数来尝试使用数组。然后,将数组声明为采用AnyObject,看看会发生什么。另外,请查看 Swift 与 Objective-C 的集成以及在 developer.apple.com/videos/wwdc/2014 的 Swift 互操作性深入讨论。系统框架仍然是 Objective-C 框架......
  • 谢谢,但后来我意识到我使用的渐变函数很奇怪。即使它是一个 ObjC 对象,渐变颜色也是在 CGColorRef 中定义的,这意味着渐变绘制方法正如预期的那样是用 C 编写的,就像大多数 Quartz 一样,所以渐变本身似乎只是 C 的 ObjC 包装器。我觉得这种迅速的变化是在框架方面合并 iOS 和 OSX 的第一步。使用 NSColor/UIColor、NSRect/CGRect 之类的东西是徒劳的。
【解决方案2】:

如果尝试将[MySwiftProtocol] 类型的数组桥接到Objective-C,也会触发此运行时错误。

解决方案是使用@objc 标记您的协议:

@objc protocol MySwiftProtocol {
   // ...
}

【讨论】:

  • 我扩展了一个 Objective-C 类以符合 Swift 协议,并且在这样做之前无法将该类类型的数组桥接到协议类型。我遇到的错误略有不同:“致命错误:无法从 Objective-C 桥接数组”。
【解决方案3】:

我发现我可以通过明确使用 CGColorRef 而不是 CGColor 作为颜色来解决问题,例如:

    var bottomColour:CGColorRef = UIColor.redColor().CGColor
    var topColour:CGColorRef = UIColor(red: 255.0/255.0, green: 123.0/255.0, blue: 37.0/255.0, alpha: 1.0).CGColor

    gradientLayer.colors = [bottomColour, topColour]

...工作正常,没有任何 NSArray 或 AnyObject 强制转换。如果我在颜色的类型声明中取出显式 CGColorRef,我会得到“数组元素无法桥接到 Objective-C”错误。

【讨论】:

  • 那行得通。谢谢。应该是这个问题的实际答案
【解决方案4】:

使用 Swift 数组,您可以对它们调用 bridgeToObjectiveC(),它们会变成 NSArrays。 Swift 字典也是如此。

【讨论】:

    【解决方案5】:

    对于任何试图让它在 Swift 中工作的人,您可以执行以下操作:

    let arrayColors: NSArray = [UIColor.blackColor().CGColor as AnyObject, UIColor.clearColor().CGColor as AnyObject]
    

    我注意到在我的 Objective-C 代码中,我将 CGColorRef 类型转换为 id。不知道为什么。如果有人有理由那就太好了!

    【讨论】:

    • 之所以CGColorRef可以桥接到id是因为CGColorRef可以使用Objective C/Cocoa的retain-release函数。在 Objective C/ARC 下,这需要桥接,但 Swift 可以自动处理 CoreFoundation 对象的内存。
    猜你喜欢
    • 2014-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-30
    • 2020-02-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多