diff --git a/KeyCommandKit/KeyBindingsRegistry.swift b/KeyCommandKit/KeyBindingsRegistry.swift index 37e894e..877ffa8 100644 --- a/KeyCommandKit/KeyBindingsRegistry.swift +++ b/KeyCommandKit/KeyBindingsRegistry.swift @@ -48,7 +48,7 @@ public class KeyBindingsRegistry typealias KeyBindingsProviderHash = Int private var providersSortOrder: [KeyBindingsProviderHash] = [] - private var keyBindings: [KeyBindingsProviderHash : [String : KeyBinding]] = [:] + private var keyBindings: [KeyBindingsProviderHash : [KeyBinding]] = [:] private var providers: [KeyBindingsProviderHash: KeyBindingsProvider.Type] = [:] private var customizations: [KeyBindingsProviderHash: [String: (input: String, modifiers: UIKeyModifierFlags)]]? = nil @@ -102,19 +102,23 @@ public class KeyBindingsRegistry /// Notice this calls the `provideKeyBindings()` method, which is *static*. public func register(keyBinding: KeyBinding, forProvider provider: KeyBindingsProvider.Type) throws { - var keyBindings = self.keyBindings[provider.providerHash] ?? [String : KeyBinding]() + var keyBindings = self.keyBindings[provider.providerHash] ?? [] - if keyBindings[keyBinding.key] == nil - { - keyBindings[keyBinding.key] = keyBinding - providers[provider.providerHash] = provider - } - else if !(keyBindings[keyBinding.key]!.isEquivalent(toKeyBinding: keyBinding)) - { - throw NSError(domain: kKeyCommandKitError, - code: 1001, - userInfo: [NSLocalizedDescriptionKey: "Consistency error: Attempted to register different key binding with same identifier: \(keyBinding.key)"]) - } + + if let existingKeyBindingIndex = keyBindings.firstIndex(where: { $0.key == keyBinding.key }) { + let existingKeyBinding = keyBindings[existingKeyBindingIndex] + + guard existingKeyBinding.isEquivalent(toKeyBinding: keyBinding) == false else { + throw NSError(domain: kKeyCommandKitError, + code: 1001, + userInfo: [NSLocalizedDescriptionKey: "Consistency error: Attempted to register different key binding with same identifier: \(keyBinding.key)"]) + } + + keyBindings.remove(at: existingKeyBindingIndex) + } + + keyBindings.append(keyBinding) + providers[provider.providerHash] = provider self.keyBindings[provider.providerHash] = keyBindings } @@ -124,7 +128,7 @@ public class KeyBindingsRegistry public func binding(withKey key: String, forProvider provider: KeyBindingsProvider.Type = GlobalKeyBindingsProvider.self) throws -> KeyBinding { - if let binding = self.keyBindings[provider.providerHash]?[key] + if let binding = self.keyBindings[provider.providerHash]?.first(where: { $0.key == key }) { return customization(forKeyBinding: binding, inProvider: provider) } @@ -144,8 +148,8 @@ public class KeyBindingsRegistry return [:] } - let customizedBindings = keyBindings.values.map({ customization(forKeyBinding: $0, inProvider: provider) }) - return zip(Array(keyBindings.keys), customizedBindings).reduce([String: KeyBinding]()) + let customizedBindings = keyBindings.map({ customization(forKeyBinding: $0, inProvider: provider) }) + return zip(keyBindings.map(\.key), customizedBindings).reduce([String: KeyBinding]()) { var dict = $0 dict[$1.0] = $1.1 @@ -374,13 +378,9 @@ internal extension KeyBindingsRegistry /// table view, and shouldn't be used for other purposes. func binding(withIndex bindingIndex: Int, forProviderWithIndex providerIndex: Int) -> KeyBinding? { - if let providerKey = keyForProvider(withIndex: providerIndex), let bindings = keyBindings[providerKey] + if let providerKey = keyForProvider(withIndex: providerIndex), let bindings = keyBindings[providerKey], bindingIndex < bindings.count { - let bindingsKeys = bindings.keys - let index = bindingsKeys.index(bindingsKeys.startIndex, offsetBy: bindingIndex) - let bindingKey = bindingsKeys[index] - - return bindings[bindingKey] + return bindings[bindingIndex] } else { @@ -434,21 +434,19 @@ internal extension KeyBindingsRegistry for (providerHash, bindings) in keyBindings { let provider = providers[providerHash]! - if let equivalentBinding = bindings.first(where: - { - _, installedBinding in - let customizedBinding = self.customization(forKeyBinding: installedBinding, inProvider: provider) + if let equivalentBinding = bindings.first(where: { installedBinding in + let customizedBinding = self.customization(forKeyBinding: installedBinding, inProvider: provider) - return customizedBinding.input.lowercased() == lookup.input.lowercased() - && customizedBinding.modifiers == lookup.modifiers - && (key == nil || customizedBinding.key != key) - }) + return customizedBinding.input.lowercased() == lookup.input.lowercased() + && customizedBinding.modifiers == lookup.modifiers + && (key == nil || customizedBinding.key != key) + }) { let providerIndex = providersSortOrder.firstIndex(of: providerHash)! return BindingConflict(providerHash: providerHash, providerIndex: providerIndex, key: equivalentBinding.key, - binding: equivalentBinding.value) + binding: equivalentBinding) } }