diff options
| author | Vadim Shpakovski | 2012-07-06 16:40:00 +0300 |
|---|---|---|
| committer | Vadim Shpakovski | 2012-07-06 16:40:00 +0300 |
| commit | 7eb4408ce34dd831ef279c182672976c8aa3f605 (patch) | |
| tree | 03f5c4f547eda26b6c3a860c8083beac4982437b /MASShortcutView+UserDefaults.m | |
| parent | 27a5c52eda2624ad89a6f9f66925cffa345160be (diff) | |
| download | MASShortcut-7eb4408ce34dd831ef279c182672976c8aa3f605.tar.bz2 | |
Adds super-easy API for associated preference key.
Diffstat (limited to 'MASShortcutView+UserDefaults.m')
| -rw-r--r-- | MASShortcutView+UserDefaults.m | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/MASShortcutView+UserDefaults.m b/MASShortcutView+UserDefaults.m new file mode 100644 index 0000000..133453e --- /dev/null +++ b/MASShortcutView+UserDefaults.m @@ -0,0 +1,115 @@ +#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 *kDefaultsObserver = &kDefaultsObserver; + +- (NSString *)associatedUserDefaultsKey +{ + MASShortcutDefaultsObserver *defaultsObserver = objc_getAssociatedObject(self, kDefaultsObserver); + return defaultsObserver.userDefaultsKey; +} + +- (void)setAssociatedUserDefaultsKey:(NSString *)associatedUserDefaultsKey +{ + MASShortcutDefaultsObserver *defaultsObserver = [[MASShortcutDefaultsObserver alloc] initWithShortcutView:self userDefaultsKey:associatedUserDefaultsKey]; + objc_setAssociatedObject(self, kDefaultsObserver, 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 standardUserDefaults] setObject:shortcut.data forKey:_userDefaultsKey]; + _internalPreferenceChange = NO; + } + else { + [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; + } +} + +@end |
