Swift beta 5中的bridgeToObjectiveC和makeObjectsPerformSelector

4

我曾在Xcode 6 beta 4中使用带有完成处理程序的代码,但在Xcode 6 beta 5中不再起作用。

dropsToRemove.bridgeToObjectiveC().makeObjectsPerformSelector("removeFromSuperview")

完整的方法...

func animateRemovingDrops(dropsToRemove: [UIView]) {
    println(__FUNCTION__)
    UIView.animateWithDuration(1.0,
        animations: {
            for dropView in dropsToRemove {
                let x = CGFloat(UInt(arc4random_uniform(UInt32(UInt(self.gameView.bounds.size.width) * 5)))) - self.gameView.bounds.size.width * 2
                let y = self.gameView.bounds.size.height
                dropView.center = CGPointMake(x, -y)
        }}, completion: { finished in
                dropsToRemove.bridgeToObjectiveC().makeObjectsPerformSelector("removeFromSuperview")
        })
}

错误是 '[UIView]' 没有名为 'bridgeToObjectiveC' 的成员
请注意,方法中的 CGFloat 和 Uint 转换是为了解决 beta 4 问题,我还没有更新该部分。该问题已在以下链接中解决: ‘CGFloat’ is not convertible to ‘UInt8' and other CGFloat issues with Swift and Xcode 6 beta 4 我认为处理完成处理程序的解决方案可能是将数组视为 NSArray,详见: What is the swift equivalent of makeObjectsPerformSelector?
(dropsToRemove as NSArray).makeObjectsPerformSelector("removeFromSuperview")

然而,假设我已经掌握了语法,只会导致另一个错误“makeObjectsPerformSelector不可用:performSelector方法不可用”。
这是一个新的Swift错误,还是我在发布说明中漏掉了什么?

他们可能只是将其添加到了禁止列表中。dropsToRemove.map { $0.removeFromSuperview() }非常简短。 - Brian Nickel
@BrianNickel,使用map来产生副作用是一种危险的先例。这不是map的目的。 - drewag
2
@drewag 很好的观点:for drop in dropsToRemove { drop.removeFromSuperview() }仍然比桥接代码要短得多。 - Brian Nickel
@BrianNickel,而且这是类型安全的 :) - drewag
感谢@BrianNickel。这应该发布为答案吗?我总是很高兴看到更好的方法,而不是使用桥接和选择器... - kasplat
@kasplat,除此之外,似乎很明显performSelector及其所有类似的方法在beta 5中已被弃用。我没有在发布说明中看到任何相关参考,但这似乎不是一个错误。 - drewag
2个回答

8

bridgeToObjectiveCbridgeFromObjectiveC 函数在 Xcode 6.0 beta 5 中不可用。相反,在需要使用该类型的 API 时,请将其强制转换为适当的 Foundation 类型。例如:

var arr = ["One", "Two"]
(arr as NSArray).indexOfObject("One")

自从Swift首个beta版本以来,苹果已经警告不要使用performSelector及其相关方法(或明确地将其禁用)。可以推测,在beta 5之前仍然可用的任何此类API都是无意中留下来的。

你提到的问题所述,您可以使用map在数组的每个元素上调用函数/方法。您还可以使用filterfindfor-in循环,或在转换为NSArray之后,使用其中一个enumerateObjects方法。请注意,许多人认为在不是“功能性”的任务中(即运行具有副作用的代码),使用函数式编程结构(mapfilterreducefind)是不好的风格。因此,for-in循环可能是实现您想要的操作最清洁的方式。


感谢@rickster。我还不得不替换像let chosenViewIndex = cardButtons.bridgeToObjectiveC().indexOfObject(sender.view as PlayingCardView)这样的代码,改为let chosenViewIndex = find(cardButtons, sender.view as PlayingCardView)!,这更清晰,但由于find()的可选结果存在问题,我之前没有使用过。 - kasplat
1
@rickster 很棒的回答!“运行具有副作用的代码”能否请您解释一下副作用或提供一些相关链接? - codester
添加了一些维基百科链接以解释这些术语。 - rickster

1

有人来自苹果表示,bridgeToObjectiveCbridgeFromObjectiveC函数是作为私有函数而设计的,即仅供苹果内部使用,并且它们将会消失。

如果您参加了开发者计划,我会尝试在开发者论坛中找到该声明的链接。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接