diff options
| -rw-r--r-- | Framework/MASDictionaryTransformer.h | 2 | ||||
| -rw-r--r-- | Framework/MASDictionaryTransformer.m | 42 | ||||
| -rw-r--r-- | Framework/MASDictionaryTransformerTests.m | 25 | ||||
| -rw-r--r-- | Framework/MASShortcutBinderTests.m | 13 | ||||
| -rw-r--r-- | Framework/Shortcut.h | 1 | ||||
| -rw-r--r-- | MASShortcut.xcodeproj/project.pbxproj | 26 |
6 files changed, 105 insertions, 4 deletions
diff --git a/Framework/MASDictionaryTransformer.h b/Framework/MASDictionaryTransformer.h new file mode 100644 index 0000000..94c5bc9 --- /dev/null +++ b/Framework/MASDictionaryTransformer.h @@ -0,0 +1,2 @@ +@interface MASDictionaryTransformer : NSValueTransformer +@end diff --git a/Framework/MASDictionaryTransformer.m b/Framework/MASDictionaryTransformer.m new file mode 100644 index 0000000..f0d9b2e --- /dev/null +++ b/Framework/MASDictionaryTransformer.m @@ -0,0 +1,42 @@ +#import "MASDictionaryTransformer.h" +#import "MASShortcut.h" + +static NSString *const MASKeyCodeKey = @"keyCode"; +static NSString *const MASModifierFlagsKey = @"modifierFlags"; + +@implementation MASDictionaryTransformer + ++ (BOOL) allowsReverseTransformation +{ + return YES; +} + +- (NSDictionary*) reverseTransformedValue: (MASShortcut*) shortcut +{ + return @{ + MASKeyCodeKey: @([shortcut keyCode]), + MASModifierFlagsKey: @([shortcut modifierFlags]) + }; +} + +- (MASShortcut*) transformedValue: (NSDictionary*) dictionary +{ + // We have to be defensive here as the value may come from user defaults. + if (![dictionary isKindOfClass:[NSDictionary class]]) { + return nil; + } + + id keyCodeBox = [dictionary objectForKey:MASKeyCodeKey]; + id modifierFlagsBox = [dictionary objectForKey:MASModifierFlagsKey]; + + SEL integerValue = @selector(integerValue); + if (![keyCodeBox respondsToSelector:integerValue] || ![modifierFlagsBox respondsToSelector:integerValue]) { + return nil; + } + + return [MASShortcut + shortcutWithKeyCode:[keyCodeBox integerValue] + modifierFlags:[modifierFlagsBox integerValue]]; +} + +@end diff --git a/Framework/MASDictionaryTransformerTests.m b/Framework/MASDictionaryTransformerTests.m new file mode 100644 index 0000000..78dfa25 --- /dev/null +++ b/Framework/MASDictionaryTransformerTests.m @@ -0,0 +1,25 @@ +#import "Shortcut.h" + +@interface MASDictionaryTransformerTests : XCTestCase +@end + +@implementation MASDictionaryTransformerTests + +- (void) testErrorHandling +{ + MASDictionaryTransformer *transformer = [MASDictionaryTransformer new]; + XCTAssertNil([transformer transformedValue:nil], + @"Decoding a shortcut from a nil dictionary returns nil."); + XCTAssertNil([transformer transformedValue:(id)@"foo"], + @"Decoding a shortcut from a invalid-type dictionary returns nil."); + XCTAssertNil([transformer transformedValue:@{}], + @"Decoding a shortcut from an empty dictionary returns nil."); + XCTAssertNil([transformer transformedValue:@{@"keyCode":@"foo"}], + @"Decoding a shortcut from a wrong-typed dictionary returns nil."); + XCTAssertNil([transformer transformedValue:@{@"keyCode":@1}], + @"Decoding a shortcut from an incomplete dictionary returns nil."); + XCTAssertNil([transformer transformedValue:@{@"modifierFlags":@1}], + @"Decoding a shortcut from an incomplete dictionary returns nil."); +} + +@end diff --git a/Framework/MASShortcutBinderTests.m b/Framework/MASShortcutBinderTests.m index 9259e9d..199eb2f 100644 --- a/Framework/MASShortcutBinderTests.m +++ b/Framework/MASShortcutBinderTests.m @@ -1,4 +1,4 @@ -#import "MASShortcutBinder.h" +#import "Shortcut.h" static NSString *const SampleDefaultsKey = @"sampleShortcut"; @@ -77,4 +77,15 @@ static NSString *const SampleDefaultsKey = @"sampleShortcut"; @"Bind after unbinding."); } +- (void) testTransformerDeserialization +{ + MASShortcut *shortcut = [MASShortcut shortcutWithKeyCode:5 modifierFlags:1048576]; + NSDictionary *storedShortcut = @{@"keyCode": @5, @"modifierFlags": @1048576}; + [_defaults setObject:storedShortcut forKey:SampleDefaultsKey]; + [_binder setBindingOptions:@{NSValueTransformerBindingOption:[MASDictionaryTransformer new]}]; + [_binder bindShortcutWithDefaultsKey:SampleDefaultsKey toAction:^{}]; + XCTAssertTrue([_monitor isShortcutRegistered:shortcut], + @"Deserialize shortcut from user defaults using a custom transformer."); +} + @end diff --git a/Framework/Shortcut.h b/Framework/Shortcut.h index dce07a5..df33f17 100644 --- a/Framework/Shortcut.h +++ b/Framework/Shortcut.h @@ -2,4 +2,5 @@ #import "MASShortcutValidator.h" #import "MASShortcutMonitor.h" #import "MASShortcutBinder.h" +#import "MASDictionaryTransformer.h" #import "MASShortcutView.h" diff --git a/MASShortcut.xcodeproj/project.pbxproj b/MASShortcut.xcodeproj/project.pbxproj index f8f29e5..ae9fde9 100644 --- a/MASShortcut.xcodeproj/project.pbxproj +++ b/MASShortcut.xcodeproj/project.pbxproj @@ -33,6 +33,9 @@ 0DC2F17C199232EA003A0131 /* MASShortcutMonitor.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D827DA419912D240010B8EF /* MASShortcutMonitor.m */; }; 0DC2F17D199232F7003A0131 /* MASShortcutBinder.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D827DAC199132840010B8EF /* MASShortcutBinder.m */; }; 0DC2F18919925F8F003A0131 /* MASShortcutBinderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DC2F18819925F8F003A0131 /* MASShortcutBinderTests.m */; }; + 0DC2F18D1993708A003A0131 /* MASDictionaryTransformer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0DC2F18B1993708A003A0131 /* MASDictionaryTransformer.h */; }; + 0DC2F18E1993708A003A0131 /* MASDictionaryTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DC2F18C1993708A003A0131 /* MASDictionaryTransformer.m */; }; + 0DC2F190199372B4003A0131 /* MASDictionaryTransformerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DC2F18F199372B4003A0131 /* MASDictionaryTransformerTests.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -94,6 +97,9 @@ 0DC2F17419922798003A0131 /* MASHotKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MASHotKey.h; path = Framework/MASHotKey.h; sourceTree = "<group>"; }; 0DC2F17519922798003A0131 /* MASHotKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MASHotKey.m; path = Framework/MASHotKey.m; sourceTree = "<group>"; }; 0DC2F18819925F8F003A0131 /* MASShortcutBinderTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MASShortcutBinderTests.m; path = Framework/MASShortcutBinderTests.m; sourceTree = "<group>"; }; + 0DC2F18B1993708A003A0131 /* MASDictionaryTransformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MASDictionaryTransformer.h; path = Framework/MASDictionaryTransformer.h; sourceTree = "<group>"; }; + 0DC2F18C1993708A003A0131 /* MASDictionaryTransformer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MASDictionaryTransformer.m; path = Framework/MASDictionaryTransformer.m; sourceTree = "<group>"; }; + 0DC2F18F199372B4003A0131 /* MASDictionaryTransformerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MASDictionaryTransformerTests.m; path = Framework/MASDictionaryTransformerTests.m; sourceTree = "<group>"; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -163,7 +169,8 @@ isa = PBXGroup; children = ( 0D827DA019912A660010B8EF /* Model */, - 0D827DA219912A870010B8EF /* Watching & Storage */, + 0D827DA219912A870010B8EF /* Monitoring */, + 0DC2F18A19937060003A0131 /* User Defaults Storage */, 0D827DA119912A6D0010B8EF /* UI */, 0D827D2F1990D5640010B8EF /* Info.plist */, 0D827D98199110F60010B8EF /* Prefix.pch */, @@ -217,18 +224,28 @@ name = UI; sourceTree = "<group>"; }; - 0D827DA219912A870010B8EF /* Watching & Storage */ = { + 0D827DA219912A870010B8EF /* Monitoring */ = { isa = PBXGroup; children = ( 0DC2F17419922798003A0131 /* MASHotKey.h */, 0DC2F17519922798003A0131 /* MASHotKey.m */, 0D827DA319912D240010B8EF /* MASShortcutMonitor.h */, 0D827DA419912D240010B8EF /* MASShortcutMonitor.m */, + ); + name = Monitoring; + sourceTree = "<group>"; + }; + 0DC2F18A19937060003A0131 /* User Defaults Storage */ = { + isa = PBXGroup; + children = ( + 0DC2F18B1993708A003A0131 /* MASDictionaryTransformer.h */, + 0DC2F18C1993708A003A0131 /* MASDictionaryTransformer.m */, + 0DC2F18F199372B4003A0131 /* MASDictionaryTransformerTests.m */, 0D827DAB199132840010B8EF /* MASShortcutBinder.h */, 0D827DAC199132840010B8EF /* MASShortcutBinder.m */, 0DC2F18819925F8F003A0131 /* MASShortcutBinderTests.m */, ); - name = "Watching & Storage"; + name = "User Defaults Storage"; sourceTree = "<group>"; }; /* End PBXGroup section */ @@ -246,6 +263,7 @@ 0D827D771990F81E0010B8EF /* Shortcut.h in Headers */, 0DC2F17619922798003A0131 /* MASHotKey.h in Headers */, 0D827D9E19911A190010B8EF /* MASShortcutValidator.h in Headers */, + 0DC2F18D1993708A003A0131 /* MASDictionaryTransformer.h in Headers */, 0D827DA519912D240010B8EF /* MASShortcutMonitor.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -376,6 +394,7 @@ 0DC2F17C199232EA003A0131 /* MASShortcutMonitor.m in Sources */, 0D827D2C1990D55E0010B8EF /* MASShortcutView.m in Sources */, 0D827D261990D55E0010B8EF /* MASShortcut.m in Sources */, + 0DC2F18E1993708A003A0131 /* MASDictionaryTransformer.m in Sources */, 0DC2F17D199232F7003A0131 /* MASShortcutBinder.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -393,6 +412,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 0DC2F190199372B4003A0131 /* MASDictionaryTransformerTests.m in Sources */, 0D827D9419910B740010B8EF /* MASShortcutTests.m in Sources */, 0DC2F18919925F8F003A0131 /* MASShortcutBinderTests.m in Sources */, ); |
