Reputation: 131
** UPDATED TO REFLECT SUGGESTED CODE AND MORE DETAILED EXPLANATION **
Trying to accomplish the following using the turorial here because I need the subclass instance to delegate functionality to the parent class eventually:
However, the original code, between '/*... */', gave the following error message:
Cannot find an initializer for type 'ClickableSKSpriteNode' that accepts an argument list of type '(imageName: String, event: (String, string2: String) -> ())'
Regarding this original code, I may not have an initializer that takes a "string", (string, string) ->()", but I do have an initializer that takes "string, Event<(String, String)>" which as far as I understood, it's supposed to take a function of type (String, String) -> () as its stead. (my understanding of how this works most likely is off I presume... I am coming from a c# background)
After making changes suggested by @rikkigibson (non commented code) below, I get a different error (sorry, don't have the code infront of me at this moment).
Anybody have any guidance as to how to change this code to accomplish what I'm trying to do?
The code in question is below:
* EVENT-RELATED CODE *
public class Event<T> {
public typealias EventHandler = T -> ()
private var eventHandlers = [Invocable]()
public func raise(data: T) {
for handler in self.eventHandlers {
handler.invoke(data)
}
}
public func addHandler<U: AnyObject>(target: U, handler: (U) -> EventHandler) -> Disposable
{
let wrapper = EventHandlerWrapper(target: target, handler: handler, event: self)
eventHandlers.append(wrapper)
return wrapper
}
}
private protocol Invocable: class {
func invoke(data: Any)
}
private class EventHandlerWrapper<T: AnyObject, U>: Invocable, Disposable {
weak var target: T?
let handler: T -> U -> ()
let event: Event<U>
init(target: T?, handler: T -> U -> (), event: Event<U>) {
self.target = target
self.handler = handler
self.event = event;
}
func invoke(data: Any) -> () {
if let t = target {
handler(t)(data as! U)
}
}
func dispose() {
event.eventHandlers = event.eventHandlers.filter { $0 !== self }
}
}
public protocol Disposable {
func dispose()
}
* SUBCLASSED SKNODE-RELATED CODE *
import SpriteKit
class ClickableSKSpriteNode: SKNode
{
let cBackground: SKSpriteNode
let event: Event<(String, String)>
let handler: AnyObject
/*init(imageName: String, event: Event<(String, String)>)*/
init(imageName: String, handler: (String, String) -> ())
{
self.cBackground = SKSpriteNode(imageNamed: imageName)
/*self.event = event*/
self.event = Event<(String, String)>()
self.handler = self.event.addHander(handler)
super.init()
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
let touch:UITouch = touches.first as! UITouch
let positionInScene = touch.locationInNode(self)
if self.cBackground.containsPoint(positionInScene) {
self.event.raise("string one", "string two")
}
}
override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) {
}
override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) {
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
* SUBCLASS OBJECT INSTANTIATION CODE *
......
let startButton = ClickableSKSpriteNode(imageName: "Start.png", event: self.handleStartClick)
......
func handleStartClick(string1: String, string2: String){
DebugPring("String1 = \(string1), String2 = \(string2)")
}
Upvotes: 0
Views: 964
Reputation: 4347
It's a simple type mismatch. Your argument to init is of type (String, String) -> ()
, not Event<(String, String)>
I suspect an Array<T -> ()>
as a member of your node subclass might be sufficient if all you need is multiple subscribers.
Upvotes: 0