SwiftのSpritekitでSKShapeNodeを用いるとiOS7.1でアプリが頻繁に落ちたのでメモ。
なお、SKShapeNodeは丸型や角丸四角などの自由な形の図形を描画したいときに用います。
以下のコードは角丸の図形を描画するコードでiOS8.1シミュレータ環境では正常に動きます。
override func didMoveToView(view: SKView) {
let tmpRect = CGRectMake(0.0, 0.0, 400, 100)
let path = CGPathCreateWithRoundedRect(tmpRect, 9, 9 , nil)
let blackRect = SKShapeNode(rect: tmpRect, cornerRadius: 10)
blackRect.fillColor = SKColor.blackColor()
blackRect.position = CGPoint(x: self.frame.width/2-blackRect.frame.width/2, y: self.frame.height/2)
self.addChild(blackRect)
}
しかし、iOS7.1環境では
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[SKShapeNode shapeNodeWithRect:cornerRadius:]: unrecognized selector sent to class 0x10614a300'
とエラーを吐いてクラッシュしてしまいます……。
このエラーは下記のコードのようにインスタンスを生成してからパスを加えることで回避することができます。
override func didMoveToView(view: SKView) {
let tmpRect = CGRectMake(0.0, 0.0, 400, 100)
let path = CGPathCreateWithRoundedRect(tmpRect, 9, 9 , nil)
let blackRect = SKShapeNode()
blackRect.path = path
blackRect.fillColor = SKColor.blackColor()
blackRect.position = CGPoint(x: self.frame.width/2-blackRect.frame.width/2, y: self.frame.height/2)
blackRect.zPosition = 10
self.addChild(blackRect)
}
しかし、このコードもiOS7.1上では問題があります。
iOS7.1にバグがあるのか、画面遷移時にアプリが稀にクラッシュしてしまいます。
xcode - Sprite Kit iOS 7.1 crash on removeFromParent - Stack Overflow
http://stackoverflow.com/questions/22399278/sprite-kit-ios-7-1-crash-on-removefromparent
例えば以下のようなコードで生成されたシーンから他のシーンに移動すると稀にクラッシュします。
(クラッシュを起きやすくさせるためにラベルの数を増やしてます)
override func didMoveToView(view: SKView) {
/* Setup your scene here */
makeLabel("hogehoge", yPosition: 100)
makeLabel("hogehoge", yPosition: 250)
makeLabel("hogehoge", yPosition: 400)
makeLabel("hogehoge", yPosition: 550)
makeLabel("hogehoge", yPosition: 700)
makeLabel("hogehoge", yPosition: 100)
makeLabel("hogehoge", yPosition: 250)
makeLabel("hogehoge", yPosition: 400)
makeLabel("hogehoge", yPosition: 550)
makeLabel("hogehoge", yPosition: 700)
}
func makeLabel(labelText:String, yPosition:CGFloat){
let myLabel = SKLabelNode(fontNamed: "PixelMplus12-Regular")
myLabel.text = labelText
myLabel.fontSize = 35
let tmpRect = CGRectMake(0.0, 0.0, 400, 100)
let blackRect = SKShapeNode()
let path = CGPathCreateWithRoundedRect(tmpRect, 9, 9 , nil)
blackRect.path = path
blackRect.fillColor = SKColor.blackColor()
blackRect.strokeColor = SKColor.whiteColor()
myLabel.position = CGPointMake(blackRect.frame.width/2, myLabel.frame.size.height*1/3)
blackRect.position = CGPoint(x: self.frame.width/2-blackRect.frame.width/2, y: yPosition)
blackRect.addChild(myLabel)
self.addChild(blackRect)
}
対応策としては以下のStack Overflowで述べられているように画面遷移前にNodeを全てcleanするのが一番簡単です。
objective c - SKShapeNode producing crash sometimes on dealloc EXC_BAD_ACCESS - Stack Overflow
http://stackoverflow.com/questions/25385510/skshapenode-producing-crash-sometimes-on-dealloc-exc-bad-access
func cleanUpChildrenAndRemove(node:SKNode) {
for child in node.children {
cleanUpChildrenAndRemove(child as SKNode)
}
node.removeFromParent()
}
他にスマートな解決策があったら教えて下さい _(:3」∠)_
以下まとめ。
ir77/TestSKShapeNode
https://github.com/ir77/TestSKShapeNode