git.y1.nz

SameBoy

Accurate GB/GBC emulator
download: https://git.y1.nz/archives/sameboy.tar.gz
README | Files | Log | Refs | LICENSE

Cocoa/NSObject+DefaultsObserver.m

      1 #import "NSObject+DefaultsObserver.h"
      2 #import <AppKit/AppKit.h>
      3 #import <objc/runtime.h>
      4 
      5 @interface GBUserDefaultsObserverHelper : NSObject
      6 @end
      7 
      8 @implementation GBUserDefaultsObserverHelper
      9 + (void)observeValueForKeyPath:(NSString *)keyPath
     10                       ofObject:(id)object
     11                         change:(NSDictionary<NSKeyValueChangeKey,id> *)change
     12                        context:(void *)context
     13 {
     14     [[NSNotificationCenter defaultCenter] postNotificationName:[keyPath stringByAppendingString:@"Changed$DefaultsObserver"]
     15                                                         object:nil
     16                                                       userInfo:@{
     17                                                           @"value": change[NSKeyValueChangeNewKey]
     18                                                       }];
     19 }
     20 
     21 + (void)startObservingKey:(NSString *)key
     22 {
     23     if (!NSThread.isMainThread) {
     24         dispatch_sync(dispatch_get_main_queue(), ^{
     25             [self startObservingKey:key];
     26         });
     27         return;
     28     }
     29     static NSMutableSet *set = nil;
     30     if (!set) {
     31         set = [NSMutableSet set];
     32     }
     33     if ([set containsObject:key]) return;
     34     [set addObject:key];
     35     [[NSUserDefaults standardUserDefaults] addObserver:(id)self
     36                                             forKeyPath:key
     37                                                options:NSKeyValueObservingOptionNew
     38                                                context:nil];
     39 }
     40 @end
     41 
     42 @implementation NSObject (DefaultsObserver)
     43 - (void)observeStandardDefaultsKey:(NSString *)key selector:(SEL)selector
     44 {
     45     __weak id weakSelf = self;
     46     [self observeStandardDefaultsKey:key
     47                            withBlock:^(id newValue) {
     48 #pragma clang diagnostic push
     49 #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
     50         [weakSelf performSelector:selector withObject:newValue];
     51 #pragma clang diagnostic pop
     52     }];
     53 }
     54 
     55 - (void)observeStandardDefaultsKey:(NSString *)key withBlock:(void(^)(id newValue))block
     56 {
     57     NSString *notificationName = [key stringByAppendingString:@"Changed$DefaultsObserver"];
     58     objc_setAssociatedObject(self, sel_registerName(notificationName.UTF8String), block, OBJC_ASSOCIATION_RETAIN);
     59     [[NSNotificationCenter defaultCenter] addObserver:self
     60                                              selector:@selector(standardDefaultsKeyChanged:)
     61                                                  name:notificationName
     62                                                object:nil];
     63     [GBUserDefaultsObserverHelper startObservingKey:key];
     64     block([[NSUserDefaults standardUserDefaults] objectForKey:key]);
     65 }
     66 
     67 - (void)standardDefaultsKeyChanged:(NSNotification *)notification
     68 {
     69     SEL selector = sel_registerName(notification.name.UTF8String);
     70     ((void(^)(id))objc_getAssociatedObject(self, selector))(notification.userInfo[@"value"]);
     71 }
     72 @end

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.