SKShapeNodeをiOS7.1で使うとクラッシュする


SwiftのSpritekitでSKShapeNodeを用いるとiOS7.1でアプリが頻繁に落ちたのでメモ。
なお、SKShapeNodeは丸型や角丸四角などの自由な形の図形を描画したいときに用います。

以下のコードは角丸の図形を描画するコードでiOS8.1シミュレータ環境では正常に動きます。

```lang:Swift
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'

とエラーを吐いてクラッシュしてしまいます……。
このエラーは下記のコードのようにインスタンスを生成してからパスを加えることで回避することができます。

```lang:Swift
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

例えば以下のようなコードで生成されたシーンから他のシーンに移動すると稀にクラッシュします。
（クラッシュを起きやすくさせるためにラベルの数を増やしてます）

```lang:Swift
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

```lang:Swift
func cleanUpChildrenAndRemove(node:SKNode) {
    for child in node.children {
        cleanUpChildrenAndRemove(child as SKNode)
    }
    node.removeFromParent()
}
```

他にスマートな解決策があったら教えて下さい \_(:3」∠)_

以下まとめ。
ir77/TestSKShapeNode
https://github.com/ir77/TestSKShapeNode