aboutsummaryrefslogtreecommitdiffstats
path: root/MASShortcutView+UserDefaults.m
diff options
context:
space:
mode:
authorTomáš Znamenáček2014-08-05 11:13:13 +0200
committerTomáš Znamenáček2015-01-07 15:05:11 +0100
commit377b44220f2a4a8b7ffc3eda9e93cf073e8a74da (patch)
treeb83239fd741773451bd9a75480ebe5a276c7d885 /MASShortcutView+UserDefaults.m
parenta3a459b4e4e47bf18dccd5dc7f315389346e3d6c (diff)
downloadMASShortcut-377b44220f2a4a8b7ffc3eda9e93cf073e8a74da.tar.bz2
Repackaged the code as a framework and included the demo.
Packaging the code as a framework is mostly just a formality. It doesn’t really change much, it just turns the code into a regular component. What it does change is that the code now has its own Xcode settings, which could make compatibility easier in the long run. Including the demo in the main repository makes it easier to hack on the library, since you can try the changes immediately. It also shows how to bundle the framework into an app that uses it.
Diffstat (limited to 'MASShortcutView+UserDefaults.m')
-rw-r--r--MASShortcutView+UserDefaults.m125
1 files changed, 0 insertions, 125 deletions
diff --git a/MASShortcutView+UserDefaults.m b/MASShortcutView+UserDefaults.m
deleted file mode 100644
index a84f0c9..0000000
--- a/MASShortcutView+UserDefaults.m
+++ /dev/null
@@ -1,125 +0,0 @@
-#import "MASShortcutView+UserDefaults.h"
-#import "MASShortcut.h"
-#import <objc/runtime.h>
-
-@interface MASShortcutDefaultsObserver : NSObject
-
-@property (nonatomic, readonly) NSString *userDefaultsKey;
-@property (nonatomic, readonly, weak) MASShortcutView *shortcutView;
-
-- (id)initWithShortcutView:(MASShortcutView *)shortcutView userDefaultsKey:(NSString *)userDefaultsKey;
-
-@end
-
-#pragma mark -
-
-@implementation MASShortcutView (UserDefaults)
-
-void *MASAssociatedDefaultsObserver = &MASAssociatedDefaultsObserver;
-
-- (NSString *)associatedUserDefaultsKey
-{
- MASShortcutDefaultsObserver *defaultsObserver = objc_getAssociatedObject(self, MASAssociatedDefaultsObserver);
- return defaultsObserver.userDefaultsKey;
-}
-
-- (void)setAssociatedUserDefaultsKey:(NSString *)associatedUserDefaultsKey
-{
- // First, stop observing previous shortcut view
- objc_setAssociatedObject(self, MASAssociatedDefaultsObserver, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
-
- if (associatedUserDefaultsKey.length == 0) return;
-
- // Next, start observing current shortcut view
- MASShortcutDefaultsObserver *defaultsObserver = [[MASShortcutDefaultsObserver alloc] initWithShortcutView:self userDefaultsKey:associatedUserDefaultsKey];
- objc_setAssociatedObject(self, MASAssociatedDefaultsObserver, defaultsObserver, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
-}
-
-@end
-
-#pragma mark -
-
-@implementation MASShortcutDefaultsObserver {
- MASShortcut *_originalShortcut;
- BOOL _internalPreferenceChange;
- BOOL _internalShortcutChange;
-}
-
-- (id)initWithShortcutView:(MASShortcutView *)shortcutView userDefaultsKey:(NSString *)userDefaultsKey
-{
- self = [super init];
- if (self) {
- _originalShortcut = shortcutView.shortcutValue;
- _shortcutView = shortcutView;
- _userDefaultsKey = userDefaultsKey.copy;
- [self startObservingShortcutView];
- }
- return self;
-}
-
-- (void)dealloc
-{
- // __weak _shortcutView is not yet deallocated because it refers MASShortcutDefaultsObserver
- [self stopObservingShortcutView];
-}
-
-#pragma mark -
-
-void *kShortcutValueObserver = &kShortcutValueObserver;
-
-- (void)startObservingShortcutView
-{
- // Read initial shortcut value from user preferences
- NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
- NSData *data = [defaults dataForKey:_userDefaultsKey];
- _shortcutView.shortcutValue = [MASShortcut shortcutWithData:data];
-
- // Observe user preferences to update shortcut value when it changed
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(userDefaultsDidChange:) name:NSUserDefaultsDidChangeNotification object:defaults];
-
- // Observe the keyboard shortcut that user inputs by hand
- [_shortcutView addObserver:self forKeyPath:@"shortcutValue" options:0 context:kShortcutValueObserver];
-}
-
-- (void)userDefaultsDidChange:(NSNotification *)note
-{
- // Ignore notifications posted from -[self observeValueForKeyPath:]
- if (_internalPreferenceChange) return;
-
- _internalShortcutChange = YES;
- NSData *data = [note.object dataForKey:_userDefaultsKey];
- _shortcutView.shortcutValue = [MASShortcut shortcutWithData:data];
- _internalShortcutChange = NO;
-}
-
-- (void)stopObservingShortcutView
-{
- // Stop observing keyboard hotkeys entered by user in the shortcut view
- [_shortcutView removeObserver:self forKeyPath:@"shortcutValue" context:kShortcutValueObserver];
-
- // Stop observing user preferences
- [[NSNotificationCenter defaultCenter] removeObserver:self name:NSUserDefaultsDidChangeNotification object:[NSUserDefaults standardUserDefaults]];
-
- // Restore original hotkey in the shortcut view
- _shortcutView.shortcutValue = _originalShortcut;
-}
-
-- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
-{
- if (context == kShortcutValueObserver) {
- if (_internalShortcutChange) return;
- MASShortcut *shortcut = [object valueForKey:keyPath];
- _internalPreferenceChange = YES;
-
- NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
- [defaults setObject:(shortcut.data ?: [NSKeyedArchiver archivedDataWithRootObject:nil]) forKey:_userDefaultsKey];
- [defaults synchronize];
-
- _internalPreferenceChange = NO;
- }
- else {
- [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
- }
-}
-
-@end