7

完了が呼び出されないのはなぜですか?

私はこれについてひどく申し訳ありません、コードダンプ...なぜなら、補完の呼び出しを除いて、このすべての部分が機能する理由がわからないからです。

完了を呼び出していない SKAction は、完了を除いてすべて実行されます。これです:

curtain.run(fadeMoveWipeAndReveal, completion: {onDone(), print("I'm done!!!!")})

次のクラス内:

import SpriteKit

class WipeCurtain: SKSpriteNode {

    var wipeCurtainBase: SKSpriteNode?
    var returnable = SKNode()
    var moveRight = SKAction()
    var node = SKNode()

    init(     color: SKColor,
              size: CGSize,
              time: TimeInterval,
              reveal: @escaping () -> (),
              onDone: @escaping () -> ())
    {
        super.init(texture: nil, color: color, size: size)
        wipeCurtainBase = SKSpriteNode(color: color, size: size)

        let show = SKAction.run(reveal)

        let fadeIn = createFadeIn(duration: time)
        let moveRight = createMoveRight(duration: time)
        let wipeRight = createWipeRight(duration: time)

        let fadeAndMove = SKAction.group( [ fadeIn, moveRight ] )
        let wipeAndReveal = SKAction.group( [ show, wipeRight ] )
        let fadeMoveWipeAndReveal = SKAction.sequence( [ fadeAndMove, wipeAndReveal ] )

        if let  curtain = self.wipeCurtainBase {
            curtain.anchorPoint = CGPoint(x: 1, y: 0)
            curtain.position = CGPoint(x: frame.size.width, y: 0)
            curtain.zPosition = -1
            curtain.name = "wipe"
            curtain.run(fadeMoveWipeAndReveal, completion: {
                onDone()
                print("I'm done!!!!")
            })
        }
    }

    func createFadeIn(duration: TimeInterval) -> SKAction {
        let fadeIn = SKEase
            .fade(
                easeFunction: .curveTypeLinear,
                easeType: .easeTypeIn,
                time: duration,
                fromValue: 0,
                toValue: 1
            )
        return fadeIn
        }

    func createMoveRight(duration: TimeInterval) -> SKAction {
        let moveRight = SKEase
            .move(
                easeFunction: .curveTypeExpo,
                easeType: .easeTypeOut,
                duration: duration,
                origin: CGPoint(
                    x: 0,
                    y: 0),
                destin: CGPoint(
                    x: frame.size.width,
                    y: 0)
            )
        return moveRight
        }

    func createWipeRight(duration: TimeInterval) -> SKAction {
        let wipeRight = SKEase
            .createFloatTween(
                start: 1,
                ender: 0,
                timer: duration,
                easer: SKEase
                    .getEaseFunction(
                        .curveTypeExpo,
                        easeType: .easeTypeOut
                    ),
            setterBlock: {(node, i) in
                node.xScale = i}
            )
        return wipeRight
        }

    func wipeWith() -> SKNode {
        if let curtain = wipeCurtainBase?.copy() as! SKSpriteNode? {
            returnable = curtain
            }
        return returnable
        }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

アップデート:

これを機能させる gameScene は、Xcode SpriteKit テンプレートの非常に軽く改造されたバージョンです。

import SpriteKit
import GameplayKit

class GameScene: SKScene {

    private var swipe: WipeCurtain?

    override func didMove(to view: SKView) {
        swipe = WipeCurtain(color: .brown, size: frame.size, time: 1,
            reveal: self.showOrNot,
            onDone: self.previewer
            )
        }

    func showOrNot(){
        print(" Deciding to show or not.......")
        }

    func previewer(){
        print("now running the previewer")
        }

    func touchDown(atPoint pos : CGPoint) {
        addChild(swipe!.wipeWith())
        }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        for t in touches { self.touchDown(atPoint: t.location(in: self)) }
        }
}
4

3 に答える 3

4

最終シーケンスで run(block: () -> ()) アクションを使用すると、目的の結果が得られますが、完了が呼び出されない理由を理解するのに役立ちません。これは単なる回避策です。

import SpriteKit

class WipeCurtain: SKSpriteNode {

    var wipeCurtainBase: SKSpriteNode?
    var returnable = SKNode()
    var moveRight = SKAction()
    var node = SKNode()

    init(     color: SKColor,
              size: CGSize,
              time: TimeInterval,
              reveal: @escaping () -> (),
              onDone: @escaping () -> ())
    {
        super.init(texture: nil, color: color, size: size)
        wipeCurtainBase = SKSpriteNode(color: color, size: size)

        let show = SKAction.run( reveal )
        let endBlock = SKAction.run( onDone )
        let fadeIn = createFadeIn(duration: time)
        let moveRight = createMoveRight(duration: time)
        let wipeRight = createWipeRight(duration: time)
        let fadeAndMove = SKAction.group( [ fadeIn, moveRight ] )
        let wipeAndReveal = SKAction.group( [ show, wipeRight ] )
        let fadeMoveWipeAndReveal = SKAction.sequence( 
                [ fadeAndMove, wipeAndReveal, endBlock ]
            )

        if let  curtain = self.wipeCurtainBase {
            curtain.anchorPoint = CGPoint(x: 1, y: 0)
            curtain.position = CGPoint(x: frame.size.width, y: 0)
            curtain.zPosition = -1
            curtain.name = "wipe"
            curtain.run(fadeMoveWipeAndReveal)
        }
    }

    func createFadeIn(duration: TimeInterval) -> SKAction {
        let fadeIn = SKEase
            .fade(
                easeFunction: .curveTypeLinear,
                easeType: .easeTypeIn,
                time: duration,
                fromValue: 0,
                toValue: 1
            )
        return fadeIn
        }

    func createMoveRight(duration: TimeInterval) -> SKAction {
        let moveRight = SKEase
            .move(
                easeFunction: .curveTypeExpo,
                easeType: .easeTypeOut,
                duration: duration,
                origin: CGPoint(
                    x: 0,
                    y: 0),
                destin: CGPoint(
                    x: frame.size.width,
                    y: 0)
            )
        return moveRight
        }

    func createWipeRight(duration: TimeInterval) -> SKAction {
        let wipeRight = SKEase
            .createFloatTween(
                start: 1,
                ender: 0,
                timer: duration,
                easer: SKEase
                    .getEaseFunction(
                        .curveTypeExpo,
                        easeType: .easeTypeOut
                    ),
            setterBlock: {(node, i) in
                node.xScale = i}
            )
        return wipeRight
        }

    func wipeWith() -> SKNode {
        if let curtain = wipeCurtainBase?.copy() as! SKSpriteNode? {
            returnable = curtain
            }
        return returnable
        }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
于 2016-12-05T21:36:41.367 に答える
1

.copy()このようにブロックやクロージャーをコピーしません。それは、バグか、Apple による計画の欠如か、または彼らが誰にも開示していない原則のいずれかです。ブロックを永続化することも、ブロックで NSCoder を使用することもできないため (afaik)、これは NSObject の問題である可能性があります。

Xcode 8 より前の観点からは、CRASH を除いて、AFAIK で何も実行する必要はありません。イニシャライザを 1 回呼び出すだけで (で実際の作業を行うものcurtain)、最初にシーンに追加しませんでした。 .

これに対して別のアプローチを取るか、思いついた回避策を使用することをお勧めします。おそらく、新しいノードの初期化は よりも高速です.copy()。パフォーマンスがどの程度かを確認するには、テストを行う必要があります。

報奨金の更新:

私の推測では、SKNode の NSObject および NSCoder 準拠です... すべてのノードは NSCoder に準拠しており、クロージャー/ブロックで NSCoder を使用することはできません。

于 2016-12-14T14:35:32.057 に答える