如何在 Swift 中继承 NSOperation 以将 SKAction 对象排队以进行串行执行? [英] How to subclass NSOperation in Swift to queue SKAction objects for serial execution?

查看:59
本文介绍了如何在 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:

In your custom implementation, you must generate KVO notifications for the isExecuting key path whenever the execution state of your operation object changes.

In your custom implementation, you must generate KVO notifications for the isFinished key path whenever the finished state of your operation object changes.

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 对象排队以进行串行执行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆