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