本文介绍了如何在 Swift 中继承 NSOperation 以将 SKAction 对象排队以进行串行执行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Rob 提供了a用于子类化 NSOperation 以实现 SKAction 对象的串行排队机制的出色 Objective-C 解决方案.我在自己的 Swift 项目中成功实现了这一点.

import SpriteKit类 ActionOperation : NSOperation{let _node: SKNode//要在其上执行操作的精灵节点let _action: SKAction//要在精灵节点上执行的动作var _finished = false//我们的super的只读finished属性的读写镜像var _executing = false//我们super的只读执行属性的读写镜像///将只读超类属性覆盖为读写.覆盖 var 执行:Bool {得到 { 返回 _executing }放 {willChangeValueForKey("isExecuting")_executing = newValuedidChangeValueForKey("isExecuting")}}///将只读超类属性覆盖为读写.覆盖变量完成:布尔{得到{返回_完成}放 {willChangeValueForKey("isFinished")_finished = 新值didChangeValueForKey("isFinished")}}///保存关闭节点和关联的动作,以便通过 start() 运行动作.初始化(节点:SKNode,动作:SKAction){//这相当于 ObjC://- (instancetype)initWithNode(SKNode *)node (SKAction *)action//请参阅 https://developer.apple.com/library/mac/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithObjective-CAPIs.html#//apple_ref/doc/uid/TP40014216 上的在 Objective-C 中公开 Swift 接口"-CH4-XID_35_node = 节点_action = 行动超级初始化()}///将节点动作添加到主操作队列中.覆盖 func start(){如果取消{完成 = 真返回}执行 = 真NSOperationQueue.mainQueue().addOperationWithBlock {self._node.runAction(self._action) {self.executing = falseself.finished = 真}}}}

要使用 ActionOperation,请在您的客户端类中实例化一个 NSOperationQueue 类成员:

var operationQueue = NSOperationQueue()

在您的 init 方法中添加这一重要行:

operationQueue.maxConcurrentOperationCount = 1;//禁止跟随动作相互重叠

然后当您准备好向其中添加 SKAction 以便它们串行运行时:

operationQueue.addOperation(ActionOperation(node: mySKNode, action: mySKAction))

您是否需要随时终止操作:

operationQueue.cancelAllOperations()//这会使队列不可用;如果需要排队更多操作,您将需要重新创建它

希望有帮助!

解决方案

根据 文档:

在您的自定义实现中,您必须在操作对象的执行状态发生变化时为 isExecuting 键路径生成 KVO 通知.

在您的自定义实现中,您必须在操作对象的完成状态发生变化时为 isFinished 键路径生成 KVO 通知.

所以我认为你必须:

override var execution:Bool {得到 { 返回 _executing }放 {willChangeValueForKey("isExecuting")_executing = newValuedidChangeValueForKey("isExecuting")}}覆盖变量完成:布尔{得到{返回_完成}放 {willChangeValueForKey("isFinished")_finished = 新值didChangeValueForKey("isFinished")}}

Rob provided a great Objective-C solution for subclassing NSOperation to achieve a serial queuing mechanism for SKAction objects. I implemented this successfully in my own Swift project.

import SpriteKit

class ActionOperation : NSOperation
{
    let _node: SKNode // The sprite node on which an action is to be performed
    let _action: SKAction // The action to perform on the sprite node
    var _finished = false // Our read-write mirror of the super's read-only finished property
    var _executing = false // Our read-write mirror of the super's read-only executing property

    /// Override read-only superclass property as read-write.
    override var executing: Bool {
        get { return _executing }
        set {
            willChangeValueForKey("isExecuting")
            _executing = newValue
            didChangeValueForKey("isExecuting")
        }
    }

    /// Override read-only superclass property as read-write.
    override var finished: Bool {
        get { return _finished }
        set {
            willChangeValueForKey("isFinished")
            _finished = newValue
            didChangeValueForKey("isFinished")
        }
    }

    /// Save off node and associated action for when it's time to run the action via start().
    init(node: SKNode, action: SKAction) {

    // This is equiv to ObjC:
    // - (instancetype)initWithNode(SKNode *)node (SKAction *)action
    // See "Exposing Swift Interfaces in Objective-C" at https://developer.apple.com/library/mac/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithObjective-CAPIs.html#//apple_ref/doc/uid/TP40014216-CH4-XID_35

        _node = node
        _action = action
        super.init()
    }

    /// Add the node action to the main operation queue.
    override func start()
    {
        if cancelled {
            finished = true
            return
        }

        executing = true

        NSOperationQueue.mainQueue().addOperationWithBlock {
            self._node.runAction(self._action) {
                self.executing = false
                self.finished = true
            }
        }
    }
}

To use the ActionOperation, instantiate an NSOperationQueue class member in your client class:

var operationQueue = NSOperationQueue()

Add this important line in your init method:

operationQueue.maxConcurrentOperationCount = 1; // disallow follow actions from overlapping one another

And then when you are ready to add SKActions to it such that they run serially:

operationQueue.addOperation(ActionOperation(node: mySKNode, action: mySKAction))

Should you need to terminate the actions at any point:

operationQueue.cancelAllOperations() // this renders the queue unusable; you will need to recreate it if needing to queue anymore actions

Hope that helps!

解决方案

According to the document:

So I think you have to:

override var executing:Bool {
    get { return _executing }
    set {
        willChangeValueForKey("isExecuting")
        _executing = newValue
        didChangeValueForKey("isExecuting")
    }
}

override var finished:Bool {
    get { return _finished }
    set {
        willChangeValueForKey("isFinished")
        _finished = newValue
        didChangeValueForKey("isFinished")
    }
}

这篇关于如何在 Swift 中继承 NSOperation 以将 SKAction 对象排队以进行串行执行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-19 01:49