Swift SKPhysicsBody 的便捷初始化程序扩展
Swift convenience initializer extension for SKPhysicsBody
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)
}
}
我在运行时遇到了这个错误
-[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'
这是我在代码中调用的方式
// redBox is a typical SKSpriteNode()
redBox.physicsBody = SKPhysicsBody(rectangleOfSize: redBox.frame.size, withAnchorPoint: redBox.anchorPoint)
我基本上想扩展 SKPhysicsBody
class 为其工厂方法提供便利的初始值设定项
正如@Cristik 在评论中猜测的那样,这是与 and this question 相同的根本问题:public SKPhysicsBody
class 是私有 PKPhysicsBody
class 提供其实现。
过去,这种方法严重依赖 Objective-C 的 "duck typing" 行为 — 只要 ClassA
响应与 ClassB
相同的所有选择器,您可以在静态类型(在源代码中向编译器声明的类型)为 ClassB
的指针上调用任何这些选择器,即使在 运行 时间的实际对象实际上是 [=12] 的实例=].
Swift 在 运行 时间类型正确性方面比 ObjC 更严格,因此仅 "duck typing" 是不够的。从 iOS 9 / OS X 10.11 开始,SpriteKit 有一些变通方法允许 PKPhysicsBody
个实例更好地伪装成 SKPhysicsBody
个实例。
但是这些并没有涵盖所有情况——特别是,它没有捕捉到 (ObjC) [SKPhysicsBody alloc]
返回一个 PKPhysicsBody
实例,这意味着任何向 [=10 添加初始值设定项的尝试=] 在 Swift 中将失败。 (因为 ObjC alloc
/init
进程在 Swift 中减少为一次初始化程序调用。)
我认为这是一个错误并推荐 filing it with Apple。
Edit/update:在该错误得到修复之前(已经一年多了),解决方法是将您的便利 "initializer" 改为 class 方法。 (如果必须的话,或者一个全局函数,但是...... ewww。)
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)
}
}
我在运行时遇到了这个错误
-[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'
这是我在代码中调用的方式
// redBox is a typical SKSpriteNode()
redBox.physicsBody = SKPhysicsBody(rectangleOfSize: redBox.frame.size, withAnchorPoint: redBox.anchorPoint)
我基本上想扩展 SKPhysicsBody
class 为其工厂方法提供便利的初始值设定项
正如@Cristik 在评论中猜测的那样,这是与 SKPhysicsBody
class 是私有 PKPhysicsBody
class 提供其实现。
过去,这种方法严重依赖 Objective-C 的 "duck typing" 行为 — 只要 ClassA
响应与 ClassB
相同的所有选择器,您可以在静态类型(在源代码中向编译器声明的类型)为 ClassB
的指针上调用任何这些选择器,即使在 运行 时间的实际对象实际上是 [=12] 的实例=].
Swift 在 运行 时间类型正确性方面比 ObjC 更严格,因此仅 "duck typing" 是不够的。从 iOS 9 / OS X 10.11 开始,SpriteKit 有一些变通方法允许 PKPhysicsBody
个实例更好地伪装成 SKPhysicsBody
个实例。
但是这些并没有涵盖所有情况——特别是,它没有捕捉到 (ObjC) [SKPhysicsBody alloc]
返回一个 PKPhysicsBody
实例,这意味着任何向 [=10 添加初始值设定项的尝试=] 在 Swift 中将失败。 (因为 ObjC alloc
/init
进程在 Swift 中减少为一次初始化程序调用。)
我认为这是一个错误并推荐 filing it with Apple。
Edit/update:在该错误得到修复之前(已经一年多了),解决方法是将您的便利 "initializer" 改为 class 方法。 (如果必须的话,或者一个全局函数,但是...... ewww。)