无法使用Swift中KeyType类型的参数列表调用方法

无法使用Swift中KeyType类型的参数列表调用方法,swift,generics,Swift,Generics,我正在Swift中使用自定义消息调度程序。我想要一个调度器,它可以: 将枚举作为事件或任何可散列的内容分派 实现一个协议的每个对象都可以添加为侦听器 代码如下: import Foundation protocol EventDispatcherProtocol: class { typealias T: Hashable func dispatcherDidDispatchEvent(event: T) } class EventListenerWrapper<T

我正在Swift中使用自定义消息调度程序。我想要一个调度器,它可以:

  • 将枚举作为事件或任何可散列的内容分派
  • 实现一个协议的每个对象都可以添加为侦听器
代码如下:

import Foundation

protocol EventDispatcherProtocol: class {
    typealias T: Hashable
    func dispatcherDidDispatchEvent(event: T)
}

class EventListenerWrapper<T: EventDispatcherProtocol> {
    weak var object: T?

    init(_ object: T) {
        self.object = object
    }
}

class EventDispatcher<KeyType: Hashable, U: EventDispatcherProtocol> {
    private var objects = Dictionary<KeyType, [EventListenerWrapper<U>]>()

    func add(#listener: U, forEvent event: KeyType) {
        let wrapper = EventListenerWrapper(object: listener)

        // get all wrappers
        if let storedWrappers = objects[event] {
            // check if there is such objects already wrapped for this type of event
            var found = false
            for storedWrapper in storedWrappers {
                if let storedObject = storedWrapper.object
                where (storedObject as! AnyObject) === (wrapper.object as! AnyObject) {
                    // Found it!
                    found = true
                    break
                }
            }

            if found == false {
                // If not found then add the wrapper for this event
                var updatedWrappers = storedWrappers
                updatedWrappers.append(wrapper)
                self.objects[event] = updatedWrappers
            }

        } else {
            self.objects[event] = [wrapper]
        }
    }

    func dispatch(event: KeyType) {
        // Enumerate through wrappers
        if let storedWrappers = objects[event] {
            var idxToRemove = [Int]()

            var currentIdx = 0
            for storedWrapper in storedWrappers {
                // if there is object to dispatch - dispatch message
                // otherwise add index of this object to remove wrapper later
                if let storedObject = storedWrapper.object {
//                    storedObject.dispatcherDidDispatchEvent(event) /// <- cannot invoke 'this method'  with an argument list of type '(KeyType)'
                } else {
                    idxToRemove.append(currentIdx)
                }

                currentIdx++
            }

            // enumerate through reversed array of indexes to remove
            // and remove items, update wrappers at the end.
            idxToRemove = idxToRemove.reverse()
            var updatedWrappers = storedWrappers
            for idx in idxToRemove {
                updatedWrappers.removeAtIndex(idx)
            }

            objects[event] = updatedWrappers
        }
    }
}



// EXAMPLE

enum CustomEvent {
    case Start, Stop
}

class CustomListener: EventDispatcherProtocol {
    func dispatcherDidDispatchEvent(event: CustomEvent) {
        println("CustomListener heard that event! \(event)")
    }
}

// Create listeners and wrap them
var listener1 = CustomListener()
var listener2 = CustomListener()

// Create dispatcher
var dispatcher = EventDispatcher<CustomEvent, CustomListener>()
dispatcher.add(listener: listener1, forEvent: CustomEvent.Start)
dispatcher.add(listener: listener2, forEvent: CustomEvent.Stop)

dispatcher.dispatch(CustomEvent.Start)
dispatcher.dispatch(CustomEvent.Stop)

storedObject.dispatcherDidDispatchEvent(event)//我认为最好的解决方案是将类声明更改为:

class EventDispatcher<U: EventDispatcherProtocol> {
    typealias KeyType = U.T
类事件调度器{
typealias键类型=U.T
它还将跳过冗余的类型声明,从而简化EventDispatcher的创建:

var dispatcher = EventDispatcher<CustomListener<CustomEvent>>()
var dispatcher=EventDispatcher()
编辑: 由于在编写答案时代码被多次修改,因此我附上了完整的解决方案代码示例:

import Foundation

protocol EventDispatcherProtocol {
    typealias T: Hashable
    func dispatcherDidDispatchEvent(event: T)
}

class EventListenerWrapper<T: EventDispatcherProtocol> {
    var object: T?

    init(object: T) {
        self.object = object
    }
}

class EventDispatcher<U: EventDispatcherProtocol> {
    typealias KeyType = U.T

    private var objects = Dictionary<KeyType, [EventListenerWrapper<U>]>()

    func add(#listener: U, forEvent event: KeyType) {
        let wrapper = EventListenerWrapper(object: listener)

        // get all wrappers
        if let storedWrappers = objects[event] {
            // check if there is such objects already wrapped for this type of event
            var found = false
            for storedWrapper in storedWrappers {
                if let storedObject = storedWrapper.object
                    where (storedObject as! AnyObject) === (wrapper.object as! AnyObject) {
                        // Found it!
                        found = true
                        break
                }
            }

            if found == false {
                // If not found then add the wrapper for this event
                var updatedWrappers = storedWrappers
                updatedWrappers.append(wrapper)
                self.objects[event] = updatedWrappers
            }

        } else {
            self.objects[event] = [wrapper]
        }
    }

    func dispatch(event: KeyType) {
        // Enumerate through wrappers
        if let storedWrappers = objects[event] {
            var idxToRemove = [Int]()

            var currentIdx = 0
            for storedWrapper in storedWrappers {
                // if there is object to dispatch - dispatch message
                // otherwise add index of this object to remove wrapper later
                if let storedObject = storedWrapper.object {
                    storedObject.dispatcherDidDispatchEvent(event) /// <- cannot invoke 'this method'  with an argument list of type '(KeyType)'
                } else {
                    idxToRemove.append(currentIdx)
                }

                currentIdx++
            }

            // enumerate through reversed array of indexes to remove
            // and remove items, update wrappers at the end.
            idxToRemove = idxToRemove.reverse()
            var updatedWrappers = storedWrappers
            for idx in idxToRemove {
                updatedWrappers.removeAtIndex(idx)
            }

            objects[event] = updatedWrappers
        }
    }
}



// EXAMPLE

enum CustomEvent {
    case Start, Stop
}

class CustomListener<T: Hashable>: EventDispatcherProtocol {
    func dispatcherDidDispatchEvent(event: T) {
        println("CustomListener heard that event! \(event)")
    }
}

// Create listeners and wrap them
var listener1 = CustomListener<CustomEvent>()
var listener2 = CustomListener<CustomEvent>()

// Create dispatcher
var dispatcher = EventDispatcher<CustomListener<CustomEvent>>()
dispatcher.add(listener: listener1, forEvent: CustomEvent.Start)
dispatcher.add(listener: listener2, forEvent: CustomEvent.Stop)

dispatcher.dispatch(CustomEvent.Start)
dispatcher.dispatch(CustomEvent.Stop)
<代码>导入基础 协议事件调度协议{ 别名T:Hashable func dispatcherDidDispatchEvent(事件:T) } 类EventListenerWrapper{ var对象:T? init(对象:T){ self.object=对象 } } 类事件调度器{ typealias键类型=U.T 私有变量对象=字典() func add(#监听器:U,forEvent事件:KeyType){ let wrapper=EventListenerWrapper(对象:侦听器) //把所有的包装纸都拿来 如果让StoredRappers=对象[事件]{ //检查是否已经为此类事件包装了此类对象 发现的var=false 对于StoredRapper中的StoredRapper{ 如果让storedObject=storedWrapper.object 其中(storedObject as!AnyObject)==(wrapper.object as!AnyObject){ //找到了! 找到=真 打破 } } 如果找到==false{ //如果未找到,则添加此事件的包装 var updatedWrappers=storedWrappers updatedWrappers.append(包装器) self.objects[event]=updatedWrappers } }否则{ self.objects[event]=[wrapper] } } func分派(事件:KeyType){ //通过包装纸列举 如果让StoredRappers=对象[事件]{ 变量idxToRemove=[Int]() var currentIdx=0 对于StoredRapper中的StoredRapper{ //如果有要分派的对象-分派消息 //否则,请添加此对象的索引,以便稍后删除包装器 如果让storedObject=storedWrapper.object{
storedObject.dispatcherDidDispatchEvent(event)///Rob Napier,CustomEvent enum在默认情况下不是可哈希的吗?可哈希与“EventDispatcher
专用的哈希类型”不同。谢谢。我开始在U.t周围胡闹,几乎在您回答之前就这样做了。无论如何,谢谢您将我直接转到这里;)
var dispatcher = EventDispatcher<CustomListener<CustomEvent>>()
import Foundation

protocol EventDispatcherProtocol {
    typealias T: Hashable
    func dispatcherDidDispatchEvent(event: T)
}

class EventListenerWrapper<T: EventDispatcherProtocol> {
    var object: T?

    init(object: T) {
        self.object = object
    }
}

class EventDispatcher<U: EventDispatcherProtocol> {
    typealias KeyType = U.T

    private var objects = Dictionary<KeyType, [EventListenerWrapper<U>]>()

    func add(#listener: U, forEvent event: KeyType) {
        let wrapper = EventListenerWrapper(object: listener)

        // get all wrappers
        if let storedWrappers = objects[event] {
            // check if there is such objects already wrapped for this type of event
            var found = false
            for storedWrapper in storedWrappers {
                if let storedObject = storedWrapper.object
                    where (storedObject as! AnyObject) === (wrapper.object as! AnyObject) {
                        // Found it!
                        found = true
                        break
                }
            }

            if found == false {
                // If not found then add the wrapper for this event
                var updatedWrappers = storedWrappers
                updatedWrappers.append(wrapper)
                self.objects[event] = updatedWrappers
            }

        } else {
            self.objects[event] = [wrapper]
        }
    }

    func dispatch(event: KeyType) {
        // Enumerate through wrappers
        if let storedWrappers = objects[event] {
            var idxToRemove = [Int]()

            var currentIdx = 0
            for storedWrapper in storedWrappers {
                // if there is object to dispatch - dispatch message
                // otherwise add index of this object to remove wrapper later
                if let storedObject = storedWrapper.object {
                    storedObject.dispatcherDidDispatchEvent(event) /// <- cannot invoke 'this method'  with an argument list of type '(KeyType)'
                } else {
                    idxToRemove.append(currentIdx)
                }

                currentIdx++
            }

            // enumerate through reversed array of indexes to remove
            // and remove items, update wrappers at the end.
            idxToRemove = idxToRemove.reverse()
            var updatedWrappers = storedWrappers
            for idx in idxToRemove {
                updatedWrappers.removeAtIndex(idx)
            }

            objects[event] = updatedWrappers
        }
    }
}



// EXAMPLE

enum CustomEvent {
    case Start, Stop
}

class CustomListener<T: Hashable>: EventDispatcherProtocol {
    func dispatcherDidDispatchEvent(event: T) {
        println("CustomListener heard that event! \(event)")
    }
}

// Create listeners and wrap them
var listener1 = CustomListener<CustomEvent>()
var listener2 = CustomListener<CustomEvent>()

// Create dispatcher
var dispatcher = EventDispatcher<CustomListener<CustomEvent>>()
dispatcher.add(listener: listener1, forEvent: CustomEvent.Start)
dispatcher.add(listener: listener2, forEvent: CustomEvent.Stop)

dispatcher.dispatch(CustomEvent.Start)
dispatcher.dispatch(CustomEvent.Stop)