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 */,  			); | 
