aleclarson / emitter-kit

Type-safe event handling for Swift
MIT License
566 stars 70 forks source link

Use enum as target #2

Closed yelled3 closed 9 years ago

yelled3 commented 9 years ago

I wanted to be able to work with emitter-kit, in the same paradigm as Backbone (http://backbonejs.org/#Events) only instead of using String for event names, I wanted to use enums.

enum EventType {
        case Start
        case Open
}
let events = ListenerStorage()

let myEvent = Event<Int>()

events += myEvent.on {
     NSLog("myEvent.on listener was called with: \($0)")
}

myEvent.emit(EventType.Start, 33) // fails at compilation

var type : AnyObject! = EventType.Start  // fails at compilation

the reason being you can't assign sturct/enum to AnyObject because they are not object type (you can use Any to hold them)

my current (somewhat hacky) solution is to do:

enum EventType : String {
        case Start = "start-event-id"
        case Open = "open-event-id"
}

and then do

myEvent.emit(EventType.Start.toRaw(), 33)

I suspect the issue with enums is the hashify func: https://github.com/aleclarson/emitter-kit/blob/master/src/Emitter.swift#L228-L230

@aleclarson any ideas?

aleclarson commented 9 years ago

Very interesting. As you can see, you're attempting to use a value type as a target when an object type is expected.

Unfortunately, other than using toRaw() with an enum EventType : String, enumeration values cannot currently be converted into Strings. There are two options that can work without any changes to EmitterKit.

1

Pass the enum value as data and use conditionals to decide whether or not to handle the event.

let myEvent = Event<(EventType, Int)>()

events += myEvent.on {
  if $0 != .Start { return }
  println($1)
}

myEvent.emit(.Start, 33)

2

Create separate events for each enum value.

let didStart = Event<Int>()
let didOpen = Event<Int>()

events += didStart.on {
  println($0)
}

didStart.emit(33)

Hope that helps! :thumbsup:

yelled3 commented 9 years ago

@aleclarson thanks for the answer :-)

the 1st solution is fairly close to what I want. however, I want to be able to pass AnyObject? as event customData:

enum EventType {
            case Start
            case Open
        }

        let events = ListenerStorage()

        let myEvent = Event<(EventType, AnyObject?)>()

        events += myEvent.on( { (ev : EventType, params : AnyObject?) -> Void in
            if ev != .Start { return }
            println(params as Array)
        })
        var eventData : AnyObject? = [33]
        myEvent.emit(.Start, ["33"]) // Could not find a user-defined conversion from type...