Epi*_*yte 7 arrays casting ios sprite-kit swift
Apple在SKPhysicsBody类中有以下方法.
/* Returns an array of all SKPhysicsBodies currently in contact with this one */
func allContactedBodies() -> [AnyObject]!
Run Code Online (Sandbox Code Playgroud)
我注意到它返回一个AnyObject数组.所以我读到了如何处理AnyObject Here
我想循环遍历物理主体的allContactedBodies数组.问题是,无论我尝试什么,我都无法让事情发挥作用.
我先试了一下:
for body in self.physicsBody.allContactedBodies() as [SKPhysicsBody] {
}
Run Code Online (Sandbox Code Playgroud)
但是我得到了这个错误.
致命错误:数组不能向下转换为派生数组
我也试过这个:
for object in self.physicsBody.allContactedBodies() {
let body = object as SKPhysicsBody
}
Run Code Online (Sandbox Code Playgroud)
但是这也崩溃了以下:

同样我试过这个:
for object in self.physicsBody.allContactedBodies() {
let body = object as? SKPhysicsBody
}
Run Code Online (Sandbox Code Playgroud)
没有崩溃,但"身体"变成零.
如果我根本不投,我不会崩溃.例如:
for object in self.physicsBody.allContactedBodies() {
}
Run Code Online (Sandbox Code Playgroud)
但显然我需要强制转换,如果我想使用实际类型.
那么作为测试,我只是尝试了这个:
let object: AnyObject = SKPhysicsBody()
let body = object as SKPhysicsBody
Run Code Online (Sandbox Code Playgroud)
这也会导致图片中出现同样的崩溃.
但其他类型不会崩溃.例如,这不会崩溃.
let object: AnyObject = SKNode()
let node = object as SKNode
Run Code Online (Sandbox Code Playgroud)
所以我的问题是,如何正确循环allContactedBodies数组?
编辑:我在iOS 8 beta 4设备上运行Xcode 6 beta 4.
编辑2:更多信息
好的,我只是做了一些测试.我试过这个:
let bodies = self.physicsBody.allContactedBodies() as? [SKPhysicsBody]
Run Code Online (Sandbox Code Playgroud)
如果"allContactedBodies"为空,则转换成功.但是如果"allContactedBodies"包含对象,则转换失败并且"body"将变为nil,因此我无法遍历它.似乎目前将AnyObject强制转换为SKPhysicsBody是不可能的,因此无法循环遍历"allContactedBodies"数组,除非有人可以提供解决方法.
编辑3:Bug仍然在Xcode 6 beta 5.下面的解决方法仍然有效
编辑4:Bug仍然在Xcode 6 beta 6.下面的解决方法仍然有效
编辑5:失望.Bug仍在Xcode 6 GM中.下面发布的解决方法仍然有效
编辑6:我收到了Apple的以下消息:
工程部提供了以下信息:
我们相信这个问题已在最新的Xcode 6.1测试版中得到解决.
但事实并非如此,该错误仍然存在于Xcode 6.1.1中!解决方法仍然有效.
编辑7: Xcode 6.3,仍然没有修复,解决方法仍然有效.
经过多次试验和错误,我找到了解决问题的方法.事实证明,当类型为AnyObject时,您根本不需要向下转换来访问SKPhysicsBody的属性.
for object in self.physicsBody.allContactedBodies() {
if object.node??.name == "surface" {
isOnSurface = true
}
}
Run Code Online (Sandbox Code Playgroud)
更新:这是一个错误,它已在iOS 9/OS X 10.11中修复.像下面这样的代码现在应该正常工作:
for body in self.physicsBody.allContactedBodies() {
// inferred type body: SKPhysicsBody
print(body.node) // call an API defined on SKPhysicsBody
}
Run Code Online (Sandbox Code Playgroud)
使用较旧的SDK /等等为后代/伙伴留下原始答案文本
在回答这个问题时,我在相关问题边栏中注意到了这一点,结果证明它是同一个根本问题.因此,虽然Epic Byte有一个可行的解决方法,但这是问题的根源,为什么解决方法有效,还有一些更多的解决方法......
这并不是说你不能施放AnyObject到SKPhysicsBody一般-它是隐藏这些特定背后的东西(一个或多个)AnyObject引用不能被强制转换为SKPhysicsBody.
返回的数组allContactedBodies()实际上包含PKPhysicsBody对象,而不是SKPhysicsBody对象.PKPhysicsBody不是公共API - 据推测,它应该是一个你看不到的实现细节.在ObjC,这是完全冷静投下PKPhysicsBody *到SKPhysicsBody *......它会"只是工作",只要你拨打仅这两个类碰巧共享的方法.但是在斯威夫特,你可以施放as/ as?/ as!只向上或向下的类型层次,以及PKPhysicsBody和SKPhysicsBody不是一个父类和子类.
你得到一个错误转换,let obj: AnyObject = SKPhysicsBody(); obj as SKPhysicsBody因为即使SKPhysicsBody初始化程序返回一个PKPhysicsBody.大多数时候你不需要经历这种舞蹈(并且让它失败),因为你SKPhysicsBody从一个声称返回的初始化器或方法中得到一个SKPhysicsBody- 所有的手工波浪铸造之间SKPhysicsBody和PKPhysicsBody正在发生的ObjC方面,Swift信任导入的ObjC API(并通过ObjC运行时调用原始API,因此尽管类型不匹配,它仍然可以像在ObjC中一样工作).
但是当你构建一个完整的数组时,需要在Swift端进行运行时类型转换,因此Swift的更严格的类型检查规则会起作用...转换PKPhysicsBody实例会使SKPhysicsBody这些规则失败,所以你崩溃了.您可以将空数组转换为[SKPhysicsBody]无错误,因为数组中没有任何冲突类型的对象(数组中没有任何对象).
Epic Byte的解决方法之所以有效,是因为Swift的AnyObject工作类似于ObjC的id类型:编译器允许您调用任何类的方法,而您只希望在运行时处理实际实现这些方法的对象.
您可以通过显式强制侧面强制转换来获得一点编译时类型安全性:
for object in self.physicsBody.allContactedBodies() {
let body = unsafeBitCast(object, SKPhysicsBody.self)
}
Run Code Online (Sandbox Code Playgroud)
在此之后,body是一个SKPhysicsBody,所以编译器将允许你只调用SKPhysicsBody它上面的方法......这就像ObjC强制转换一样,所以你仍然希望你调用的方法实际上是由你正在谈论的对象实现的.但至少编译器可以帮助你保持诚实.(你不能unsafeBitCast使用数组类型,因此必须在循环内部对元素执行此操作.)
这应该被认为是一个错误,所以请让Apple知道它是否会影响你.
| 归档时间: |
|
| 查看次数: |
1734 次 |
| 最近记录: |