Skip to content

Instantly share code, notes, and snippets.

@mxpr
Last active August 29, 2015 14:26
Show Gist options
  • Save mxpr/9f98d1fd6c314897dff0 to your computer and use it in GitHub Desktop.
Save mxpr/9f98d1fd6c314897dff0 to your computer and use it in GitHub Desktop.
KeyedCallbacks
protocol KeyValueStore
{
func valueForKey(key: String) -> String
func setValue(value: String, forKey key: String)
func removeValueForKey(key: String)
}
class DictionaryKeyValueStore : KeyValueStore
{
private var store = [String : String]()
// MARK: KeyValueStore
func valueForKey(key: String) -> String?
{
return store[key]
}
func setValue(value: String, forKey key: String)
{
store[key] = value
}
func removeValueForKey(key: String)
{
store.removeValueForKey(key)
}
}
protocol KeyValueStore
{
func valueForKey(key: String) -> String
func setValue(value: String, forKey key: String)
func removeValueForKey(key: String)
func registerForUpdates(key: String, callback: (key: String, newValue:String)->Void)
}
class DictionaryKeyValueStore : KeyValueStore
{
typealias UpdatesCallback = (key: String, newValue:String?)->Void
private var store = [String : String]()
private var keyedCallbacks = [String: [UpdatesCallback]]()
// MARK: KeyValueStore
func valueForKey(key: String) -> String?
{
return store[key]
}
func setValue(value: String, forKey key: String)
{
store[key] = value
notifyChanges(key, newValue: value)
}
func removeValueForKey(key: String)
{
store.removeValueForKey(key)
notifyChanges(key, newValue: nil)
}
func registerForUpdates(key: String, callback: UpdatesCallback)
{
if var keyCallbacks = keyedCallbacks[key]
{
keyCallbacks.append(callback)
keyedCallbacks[key] = keyCallbacks
}
else
{
keyedCallbacks[key] = [callback]
}
}
// MARK: Private
private func notifyChanges(key: String, newValue: String?)
{
if let keyCallbacks = keyedCallbacks[key]
{
for callback in keyCallbacks
{
callback(key: key, newValue: newValue)
}
}
}
}
class KeyedCallbacks<CallbackParameters>
{
typealias Callback = (CallbackParameters) -> Void
private var keyedCallbacks = [String: [Callback]]()
func register(key: String, callback: Callback)
{
if var keyCallbacks = keyedCallbacks[key]
{
keyCallbacks.append(callback)
keyedCallbacks[key] = keyCallbacks
}
else
{
keyedCallbacks[key] = [callback]
}
}
func performCallbacksForKey(key:String, withParameters parameters: CallbackParameters)
{
if let keyCallbacks = keyedCallbacks[key]
{
for callback in keyCallbacks
{
callback(parameters)
}
}
}
}
class DictionaryKeyValueStore : KeyValueStore
{
typealias CallbackParameters = (key: String, newValue:String?)
typealias UpdatesCallback = CallbackParameters->Void
private var store = [String : String]()
private var keyedCallbacks = KeyedCallbacks<CallbackParameters>()
// MARK: KeyValueStore
func valueForKey(key: String) -> String?
{
return store[key]
}
func setValue(value: String, forKey key: String)
{
store[key] = value
notifyChanges(key, newValue: value)
}
func removeValueForKey(key: String)
{
store.removeValueForKey(key)
notifyChanges(key, newValue: nil)
}
func registerForUpdates(key: String, callback: UpdatesCallback)
{
keyedCallbacks.register(key , callback: callback)
}
// MARK: Private
private func notifyChanges(key: String, newValue: String?)
{
keyedCallbacks.performCallbacksForKey(key, withParameters: (key: key, newValue: newValue ))
}
}
func deregister(key: String, callback: Callback)
{
if var keyCallbacks = keyedCallbacks[key],
index = keyCallbacks.indexOf(callback) // This does not work!
{
keyCallbacks.removeAtIndex(index)
if keyCallbacks.count > 0
{
keyedCallbacks[key] = keyCallbacks
}
else
{
keyedCallbacks.removeValueForKey(key)
}
}
}
protocol CallbackHandle
{
}
// ..
func register(key: String, callback: Callback) -> CallbackHandle
func deregister(handle: CallbackHandle)
// ..
public protocol CallbackHandle
{
}
private class KeyedCallbackHandle<CallbackParameters> : CallbackHandle, Equatable
{
typealias Callback = (CallbackParameters) -> Void
let key: String
let callback : Callback
init(key: String, callback: Callback)
{
self.key = key
self.callback = callback
}
}
private func ==<T>(lhs: KeyedCallbackHandle<T>, rhs: KeyedCallbackHandle<T>) -> Bool
{
return lhs === rhs
}
public class KeyedCallbacks<CallbackParameters>
{
typealias Callback = (CallbackParameters) -> Void
private var keyedHandles = [String: [KeyedCallbackHandle<CallbackParameters>]]()
public init()
{
}
public func register(key: String, callback: Callback) -> CallbackHandle
{
let handle = KeyedCallbackHandle<CallbackParameters>(key:key, callback:callback)
if var handles = keyedHandles[key]
{
handles.append(handle)
keyedHandles[key] = handles
}
else
{
keyedHandles[key] = [handle]
}
return handle
}
public func deregister(handle: CallbackHandle)
{
if let keyedCallbackHandle = handle as? KeyedCallbackHandle<CallbackParameters>,
var handles = keyedHandles[keyedCallbackHandle.key],
let index = handles.indexOf(keyedCallbackHandle)
{
handles.removeAtIndex(index)
if handles.count > 0
{
keyedHandles[keyedCallbackHandle.key] = handles
}
else
{
keyedHandles.removeValueForKey(keyedCallbackHandle.key)
}
}
}
public func performCallbacksForKey(key:String, withParameters parameters: CallbackParameters)
{
if let handles = keyedHandles[key]
{
for handle in handles
{
handle.callback(parameters)
}
}
}
}
private class KeyedCallbackHandle<CallbackParameters> : CallbackHandle, Equatable
{
typealias Callback = (CallbackParameters) -> Void
let key: String
let callback : Callback
var onDeinit : (()->Void)?
init(key: String, callback: Callback)
{
self.key = key
self.callback = callback
}
deinit
{
onDeinit?()
}
}
// ..
public func register(key: String, callback: Callback) -> CallbackHandle
{
let handle = KeyedCallbackHandle<CallbackParameters>(key:key, callback:callback)
handle.onDeinit = { [weak self, weak handle] in
if let s = self, let h = handle
{
s.deregister(h)
}
}
if var handles = keyedHandles[key]
{
handles.append(handle)
keyedHandles[key] = handles
}
else
{
keyedHandles[key] = [handle]
}
return handle
}
// ..
private class WeakKeyedCallbackHandle<CallbackParameters> : Equatable
{
weak var handle : KeyedCallbackHandle<CallbackParameters>?
init(_ handle: KeyedCallbackHandle<CallbackParameters>)
{
self.handle = handle
}
}
private func ==<T>(lhs: WeakKeyedCallbackHandle<T>, rhs: WeakKeyedCallbackHandle<T>) -> Bool
{
return lhs.handle == rhs.handle
}
public class KeyedCallbacks<CallbackParameters>
{
typealias Callback = (CallbackParameters) -> Void
private var keyedHandles = [String: [WeakKeyedCallbackHandle<CallbackParameters>]]()
public init()
{
}
public func register(key: String, callback: Callback) -> CallbackHandle
{
let handle = KeyedCallbackHandle<CallbackParameters>(key:key, callback:callback)
handle.onDeinit = { [weak self, weak handle] in
if let s = self, let h = handle
{
s.deregister(h)
}
}
let weakHandle = WeakKeyedCallbackHandle(handle)
if var handles = keyedHandles[key]
{
handles.append(weakHandle)
keyedHandles[key] = handles
}
else
{
keyedHandles[key] = [weakHandle]
}
return handle
}
public func deregister(handle: CallbackHandle)
{
if let keyedCallbackHandle = handle as? KeyedCallbackHandle<CallbackParameters>,
var handles = keyedHandles[keyedCallbackHandle.key],
let index = handles.indexOf(WeakKeyedCallbackHandle(handle))
{
handles.removeAtIndex(index)
if handles.count > 0
{
keyedHandles[keyedCallbackHandle.key] = handles
}
else
{
keyedHandles.removeValueForKey(keyedCallbackHandle.key)
}
}
}
public func performCallbacksForKey(key:String, withParameters parameters: CallbackParameters)
{
if let weakHandles = keyedHandles[key]
{
for weakHandle in weakHandles
{
weakHandle.handle?.callback(parameters)
}
}
}
}
private class KeyedCallbackHandles<CallbackParameters>
{
private var keyedHandles = [String: [WeakKeyedCallbackHandle<CallbackParameters>]]()
func add(handle: KeyedCallbackHandle<CallbackParameters>)
{
handle.onDeinit = { [weak self, weak handle] in
if let s = self, let h = handle
{
s.remove(h)
}
}
let weakHandle = WeakKeyedCallbackHandle(handle)
if var handles = keyedHandles[handle.key]
{
handles.append(weakHandle)
keyedHandles[handle.key] = handles
}
else
{
keyedHandles[handle.key] = [weakHandle]
}
}
func remove(handle: KeyedCallbackHandle<CallbackParameters>)
{
if var handles = keyedHandles[handle.key],
let index = handles.indexOf(WeakKeyedCallbackHandle(handle))
{
handles.removeAtIndex(index)
if handles.count > 0
{
keyedHandles[handle.key] = handles
}
else
{
keyedHandles.removeValueForKey(handle.key)
}
}
}
func handlesForKey(key: String) -> [KeyedCallbackHandle<CallbackParameters>]?
{
var handles : [KeyedCallbackHandle<CallbackParameters>]?
if let weakHandles = keyedHandles[key]
{
handles = weakHandles.flatMap({ $0.handle })
}
return handles
}
}
public class KeyedCallbacks<CallbackParameters>
{
typealias Callback = (CallbackParameters) -> Void
private var keyedHandles = KeyedCallbackHandles<CallbackParameters>()
public init()
{
}
public func register(key: String, callback: Callback) -> CallbackHandle
{
let handle = KeyedCallbackHandle<CallbackParameters>(key:key, callback:callback)
keyedHandles.add(handle)
return handle
}
public func deregister(handle: CallbackHandle)
{
if let keyedCallbackHandle = handle as? KeyedCallbackHandle<CallbackParameters>
{
keyedHandles.remove(keyedCallbackHandle)
}
}
public func performCallbacksForKey(key:String, withParameters parameters: CallbackParameters)
{
if let handles = keyedHandles.handlesForKey(key)
{
for handle in handles
{
handle.callback(parameters)
}
}
}
}
// ..
class DictionaryKeyValueStore : KeyValueStore
{
// ..
private var keyedCallbacks = KeyedCallbacks<CallbackParameters>()
// ..
func registerForUpdates(key: String, callback: UpdatesCallback) -> CallbackHandle
{
return keyedCallbacks.register(key , callback: callback)
}
// ..
}
// ..
public func usage()
{
let keyValueStore = DictionaryKeyValueStore()
let handle1 = keyValueStore.registerForUpdates("a") { print(" ## \($0)") }
unused(handle1)
do
{
let handle2 = keyValueStore.registerForUpdates("a") { print(" >> \($0)") }
unused(handle2)
keyValueStore.setValue("cool!", forKey: "a")
//prints
//
// ## ("a", Optional("cool!"))
// >> ("a", Optional("cool!"))
}
keyValueStore.setValue("warmer", forKey: "a")
//prints
//
// ## ("a", Optional("warmer"))
}
public func unused(_ : Any)
{
// This is needed to supress the unused variable warning
}
// MARK: Keyed Callbacks
public protocol CallbackHandle
{
}
private class KeyedCallbackHandle<CallbackParameters> : CallbackHandle, Equatable
{
typealias Callback = (CallbackParameters) -> Void
let key: String
let callback : Callback
var onDeinit : (()->Void)?
init(key: String, callback: Callback)
{
self.key = key
self.callback = callback
}
deinit
{
onDeinit?()
}
}
private func ==<T>(lhs: KeyedCallbackHandle<T>, rhs: KeyedCallbackHandle<T>) -> Bool
{
return lhs === rhs
}
private class WeakKeyedCallbackHandle<CallbackParameters> : Equatable
{
weak var handle : KeyedCallbackHandle<CallbackParameters>?
init(_ handle: KeyedCallbackHandle<CallbackParameters>)
{
self.handle = handle
}
}
private func ==<T>(lhs: WeakKeyedCallbackHandle<T>, rhs: WeakKeyedCallbackHandle<T>) -> Bool
{
return lhs.handle == rhs.handle
}
private class KeyedCallbackHandles<CallbackParameters>
{
private var keyedHandles = [String: [WeakKeyedCallbackHandle<CallbackParameters>]]()
func add(handle: KeyedCallbackHandle<CallbackParameters>)
{
handle.onDeinit = { [weak self, weak handle] in
if let s = self, let h = handle
{
s.remove(h)
}
}
let weakHandle = WeakKeyedCallbackHandle(handle)
if var handles = keyedHandles[handle.key]
{
handles.append(weakHandle)
keyedHandles[handle.key] = handles
}
else
{
keyedHandles[handle.key] = [weakHandle]
}
}
func remove(handle: KeyedCallbackHandle<CallbackParameters>)
{
if var handles = keyedHandles[handle.key],
let index = handles.indexOf(WeakKeyedCallbackHandle(handle))
{
handles.removeAtIndex(index)
if handles.count > 0
{
keyedHandles[handle.key] = handles
}
else
{
keyedHandles.removeValueForKey(handle.key)
}
}
}
func handlesForKey(key: String) -> [KeyedCallbackHandle<CallbackParameters>]?
{
var handles : [KeyedCallbackHandle<CallbackParameters>]?
if let weakHandles = keyedHandles[key]
{
handles = weakHandles.flatMap({ $0.handle })
}
return handles
}
}
public class KeyedCallbacks<CallbackParameters>
{
typealias Callback = (CallbackParameters) -> Void
private var keyedHandles = KeyedCallbackHandles<CallbackParameters>()
public init()
{
}
public func register(key: String, callback: Callback) -> CallbackHandle
{
let handle = KeyedCallbackHandle<CallbackParameters>(key:key, callback:callback)
keyedHandles.add(handle)
return handle
}
public func deregister(handle: CallbackHandle)
{
if let keyedCallbackHandle = handle as? KeyedCallbackHandle<CallbackParameters>
{
keyedHandles.remove(keyedCallbackHandle)
}
}
public func performCallbacksForKey(key:String, withParameters parameters: CallbackParameters)
{
if let handles = keyedHandles.handlesForKey(key)
{
for handle in handles
{
handle.callback(parameters)
}
}
}
}
// MARK: Key Value Store
protocol KeyValueStore
{
func valueForKey(key: String) -> String?
func setValue(value: String, forKey key: String)
func removeValueForKey(key: String)
func registerForUpdates(key: String, callback: (key: String, newValue:String?)->Void) -> CallbackHandle
}
class DictionaryKeyValueStore : KeyValueStore
{
typealias CallbackParameters = (key: String, newValue:String?)
typealias UpdatesCallback = CallbackParameters->Void
private var store = [String : String]()
private var keyedCallbacks = KeyedCallbacks<CallbackParameters>()
// MARK: KeyValueStore
func valueForKey(key: String) -> String?
{
return store[key]
}
func setValue(value: String, forKey key: String)
{
store[key] = value
notifyChanges(key, newValue: value)
}
func removeValueForKey(key: String)
{
store.removeValueForKey(key)
notifyChanges(key, newValue: nil)
}
func registerForUpdates(key: String, callback: UpdatesCallback) -> CallbackHandle
{
return keyedCallbacks.register(key , callback: callback)
}
// MARK: Private
private func notifyChanges(key: String, newValue: String?)
{
keyedCallbacks.performCallbacksForKey(key, withParameters: (key: key, newValue: newValue ))
}
}
public func unused(_ : Any)
{
// This is needed to supress the unused variable warning
}
public func usage()
{
let keyValueStore = DictionaryKeyValueStore()
let handle1 = keyValueStore.registerForUpdates("a") { print(" ## \($0)") }
unused(handle1)
do
{
let handle2 = keyValueStore.registerForUpdates("a") { print(" >> \($0)") }
unused(handle2)
keyValueStore.setValue("cool!", forKey: "a")
//prints
//
// ## ("a", Optional("cool!"))
// >> ("a", Optional("cool!"))
}
keyValueStore.setValue("warmer", forKey: "a")
//prints
//
// ## ("a", Optional("warmer"))
}
@mxpr
Copy link
Author

mxpr commented Aug 2, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment