node.physicsBody.joints ошибка downcasting
Следующий код выдает ошибку - кажется, что массив физических соединений имеет класс PKPhysicsJoint. У кого-нибудь есть идеи, как я могу перебирать соединения в Swift?
В документации сказано, что physBody.joints должен возвращать массив SKPhysicsJoint.
import SpriteKit
let scene = SKScene(size: CGSize(width: 200, height: 200))
let nodeA = SKNode()
let nodeB = SKNode()
nodeA.physicsBody = SKPhysicsBody(circleOfRadius: 20)
nodeB.physicsBody = SKPhysicsBody(circleOfRadius: 20)
scene.addChild(nodeA)
scene.addChild(nodeB)
let joint = SKPhysicsJointFixed.jointWithBodyA(nodeA.physicsBody, bodyB: nodeB.physicsBody, anchor: CGPointZero)
scene.physicsWorld.addJoint(joint)
for joint in nodeA.physicsBody!.joints as [SKPhysicsJoint] {
// do something else here
}
выдает ошибку:
Execution was interrupted. reason: EXC_BAD_INSTRUCTION...
1 ответ
Обновление: это была ошибка, и она исправлена в iOS 9 / OS X 10.11 - код в вопросе только сейчас работает.
Оставить оригинальный текст ответа для потомков / людей, использующих старые SDK / и т. Д.
Это похоже на ошибку - вы должны подать его. Трудно сказать, следует ли считать это ошибкой SpriteKit или Swift, но это проблема Apple, а не ваша.:)
Проблема ясна, если вы вставите свой код в игровую площадку - ваш joint
на самом деле PKPhysicsJointWeld
за кулисами. Это некоторый внутренний класс, который должен быть деталью реализации. В ObjC это не проблема, потому что приведение в C - это просто сказать компилятору: "Поверьте мне, этот указатель действительно SKPhysicsJoint
так что позвольте мне назвать физические совместные методы (и ничто иное) для него, и никто не станет мудрее ". Приведение в Swift требует, чтобы между приведенными типами были отношения иерархии типов - и PKPhysicsJointWeld
не является подтипом / подклассом SKPhysicsJoint
так что актерский состав проваливается.
Вы можете обойти эту проблему, избегая приведения к [SKPhysicsJoint]
:
for joint in nodeA.physicsBody!.joints {
// do something else here
}
При этом вы теряете некоторую безопасность типов - joint
является AnyObject
так как у ObjC id
Тип компилятор позволяет вам вызывать любой метод на нем. (И может произойти сбой во время выполнения, если этот объект не реализует метод.) Но, по крайней мере, он работает.
Еще один обходной путь: внутри цикла вы можете разыграть joint
в SKPhysicsJoint
, Но так как это приведение происходит через иерархию типов, вы должны использовать unsafeBitCast
:
for joint in nodeA.physicsBody!.joints {
let skJoint = unsafeBitCast(joint, SKPhysicsJoint.self)
// do stuff with skJoint
}
Это вернет вам немного "типа безопасности" времени компиляции, так как после этого компилятору потребуется все, что вы делаете с skJoint
быть совместимым с SKPhysicsJoint
, но это по-прежнему небезопасно в том смысле, что зависит от некоторых размахиваний руками вокруг типов времени выполнения, которые могут не всегда выполняться. И ты должен unsafeBitCast
снова, чтобы добраться до определенного совместного подкласса, не зная, каким подклассом это может быть. (Опять же, сейчас самое время подать ошибку.)
(Вы можете заметить, что при вставке на игровую площадку physicsWorld
также имеет внутренний класс: PKPhysicsWorld
, Так почему же это не сработает? Когда вы используете physicsWorld
Свойство, все приведение типов происходит на стороне ObjC, и Swift доверяет всему, что ObjC сообщает. Когда вы имеете дело с joints
массив, однако, вы должны выполнить приведение типов на стороне Swift, и Swift гораздо более строг в проверке типов.)