问题
extension SKPhysicsBody {
/// anchorPoint version of init(rectangleOfSize:center:)
convenience init(rectangleOfSize s: CGSize, withAnchorPoint anchorPoint: CGPoint) {
var center = CGPoint()
center.x = (s.width / 2) - ( s.width * anchorPoint.x)
center.y = (s.height / 2 ) - ( s.height * anchorPoint.y)
self.init(rectangleOfSize: s, center: center)
}
}
I got this error on runtime
-[PKPhysicsBody initWithRectangleOfSize:withAnchorPoint:]: unrecognized selector sent to instance 0x7f9b03c4fff0
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[PKPhysicsBody initWithRectangleOfSize:withAnchorPoint:]: unrecognized selector sent to instance 0x7f9b03c4fff0'
This is how I call in code
// redBox is a typical SKSpriteNode()
redBox.physicsBody = SKPhysicsBody(rectangleOfSize: redBox.frame.size, withAnchorPoint: redBox.anchorPoint)
I basically want to extend the SKPhysicsBody
class to provide a convenience initializer to its factory method
回答1:
As @Cristik guessed in the comments, this is the same root problem as this question and this question: the public SKPhysicsBody
class is a convenience interface for the private PKPhysicsBody
class that provides its implementation.
In the past, this approach relied heavily on the "duck typing" behavior of Objective-C — as long as ClassA
responds to all the same selectors as ClassB
, you can call any of those selectors on a pointer whose static type (the type declared to the compiler in source code) is ClassB
, even if the actual object at run time is really an instance of ClassA
.
Swift is stricter about runtime type correctness than ObjC, so "duck typing" alone is not enough. Since iOS 9 / OS X 10.11, SpriteKit has some workarounds that allow PKPhysicsBody
instances to better pretend to be SKPhysicsBody
instances.
But those don't cover all cases — in particular, it doesn't catch (ObjC) [SKPhysicsBody alloc]
returning a PKPhysicsBody
instance, which means any attempt to add initializers to SKPhysicsBody
in Swift will fail. (Because the ObjC alloc
/init
process is reduced to one initializer call in Swift.)
I'd consider this a bug and recommend filing it with Apple.
Edit/update: And until that bug gets fixed (it's been a year and some now), the workaround is to make your convenience "initializer" into a class method instead. (Or a global function if you must, but... ewww.)
来源:https://stackoverflow.com/questions/34894762/swift-convenience-initializer-extension-for-skphysicsbody