aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Framework/MASDictionaryTransformer.h2
-rw-r--r--Framework/MASDictionaryTransformer.m42
-rw-r--r--Framework/MASDictionaryTransformerTests.m25
-rw-r--r--Framework/MASShortcutBinderTests.m13
-rw-r--r--Framework/Shortcut.h1
-rw-r--r--MASShortcut.xcodeproj/project.pbxproj26
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 */,
);