Просмотр исходного кода

Add option to disable property/ivar previews

Tanner Bennett лет назад: 6
Родитель
Сommit
88c7ca9373

+ 12 - 0
Classes/ObjectExplorers/FLEXObjectExplorer.h

@@ -8,10 +8,22 @@
 
 
 #import "FLEXRuntime+UIKitHelpers.h"
 #import "FLEXRuntime+UIKitHelpers.h"
 
 
+/// Carries state about the current user defaults settings
+@interface FLEXObjectExplorerDefaults : NSObject
++ (instancetype)canEdit:(BOOL)editable wantsPreviews:(BOOL)showPreviews;
+
+/// Only \c YES for properties and ivars
+@property (nonatomic, readonly) BOOL isEditable;
+/// Only affects properties and ivars
+@property (nonatomic, readonly) BOOL wantsDynamicPreviews;
+@end
+
 @interface FLEXObjectExplorer : NSObject
 @interface FLEXObjectExplorer : NSObject
 
 
 + (instancetype)forObject:(id)objectOrClass;
 + (instancetype)forObject:(id)objectOrClass;
 
 
++ (void)configureDefaultsForItems:(NSArray<id<FLEXObjectExplorerItem>> *)items;
+
 @property (nonatomic, readonly) id object;
 @property (nonatomic, readonly) id object;
 /// Subclasses can override to provide a more useful description
 /// Subclasses can override to provide a more useful description
 @property (nonatomic, readonly) NSString *objectDescription;
 @property (nonatomic, readonly) NSString *objectDescription;

+ 30 - 3
Classes/ObjectExplorers/FLEXObjectExplorer.m

@@ -17,6 +17,17 @@
 #import "FLEXMetadataSection.h"
 #import "FLEXMetadataSection.h"
 #import "NSUserDefaults+FLEX.h"
 #import "NSUserDefaults+FLEX.h"
 
 
+@implementation FLEXObjectExplorerDefaults
+
++ (instancetype)canEdit:(BOOL)editable wantsPreviews:(BOOL)showPreviews {
+    FLEXObjectExplorerDefaults *defaults = [self new];
+    defaults->_isEditable = editable;
+    defaults->_wantsDynamicPreviews = showPreviews;
+    return defaults;
+}
+
+@end
+
 @interface FLEXObjectExplorer () {
 @interface FLEXObjectExplorer () {
     NSMutableArray<NSArray<FLEXProperty *> *> *_allProperties;
     NSMutableArray<NSArray<FLEXProperty *> *> *_allProperties;
     NSMutableArray<NSArray<FLEXProperty *> *> *_allClassProperties;
     NSMutableArray<NSArray<FLEXProperty *> *> *_allClassProperties;
@@ -55,6 +66,24 @@
 
 
 #pragma mark - Public
 #pragma mark - Public
 
 
++ (void)configureDefaultsForItems:(NSArray<id<FLEXObjectExplorerItem>> *)items {
+    BOOL hidePreviews = NSUserDefaults.standardUserDefaults.flex_explorerHidesVariablePreviews;
+    FLEXObjectExplorerDefaults *mutable = [FLEXObjectExplorerDefaults
+        canEdit:YES wantsPreviews:!hidePreviews
+    ];
+    FLEXObjectExplorerDefaults *immutable = [FLEXObjectExplorerDefaults
+        canEdit:NO wantsPreviews:!hidePreviews
+    ];
+
+    // .tag is used to cache whether the value of .isEditable;
+    // This could change at runtime so it is important that
+    // it is cached every time shortcuts are requeted and not
+    // just once at as shortcuts are initially registered
+    for (id<FLEXObjectExplorerItem> metadata in items) {
+        metadata.defaults = metadata.isEditable ? mutable : immutable;
+    }
+}
+
 - (NSString *)objectDescription {
 - (NSString *)objectDescription {
     if (!_objectDescription) {
     if (!_objectDescription) {
         // Hard-code UIColor description
         // Hard-code UIColor description
@@ -224,9 +253,7 @@
     // because no other metadata types support editing.
     // because no other metadata types support editing.
     for (NSArray *matrix in @[_allProperties, _allIvars, /* _allMethods, _allClassMethods, _allConformedProtocols */]) {
     for (NSArray *matrix in @[_allProperties, _allIvars, /* _allMethods, _allClassMethods, _allConformedProtocols */]) {
         for (NSArray *metadataByClass in matrix) {
         for (NSArray *metadataByClass in matrix) {
-            for (id<FLEXRuntimeMetadata> metadata in metadataByClass) {
-                metadata.tag = metadata.isEditable ? @YES : nil;
-            }
+            [FLEXObjectExplorer configureDefaultsForItems:metadataByClass];
         }
         }
     }
     }
     
     

+ 10 - 12
Classes/ObjectExplorers/FLEXObjectExplorerViewController.m

@@ -73,6 +73,7 @@
         kFLEXDefaultsHidePropertyIvarsKey,
         kFLEXDefaultsHidePropertyIvarsKey,
         kFLEXDefaultsHidePropertyMethodsKey,
         kFLEXDefaultsHidePropertyMethodsKey,
         kFLEXDefaultsHideMethodOverridesKey,
         kFLEXDefaultsHideMethodOverridesKey,
+        kFLEXDefaultsHideVariablePreviewsKey,
     ];
     ];
 }
 }
 
 
@@ -122,12 +123,7 @@
     //
     //
     // "If your app targets iOS 9.0 and later or macOS 10.11 and later,
     // "If your app targets iOS 9.0 and later or macOS 10.11 and later,
     // you don't need to unregister an observer in its dealloc method."
     // you don't need to unregister an observer in its dealloc method."
-    NSArray<NSString *> *observedNotifications = @[
-        kFLEXDefaultsHidePropertyIvarsKey,
-        kFLEXDefaultsHidePropertyMethodsKey,
-        kFLEXDefaultsHideMethodOverridesKey,
-    ];
-    for (NSString *pref in observedNotifications) {
+    for (NSString *pref in self.observedNotifications) {
         [NSNotificationCenter.defaultCenter
         [NSNotificationCenter.defaultCenter
             addObserver:self
             addObserver:self
             selector:@selector(fullyReloadData)
             selector:@selector(fullyReloadData)
@@ -293,9 +289,10 @@
     NSUserDefaults *defaults = NSUserDefaults.standardUserDefaults;
     NSUserDefaults *defaults = NSUserDefaults.standardUserDefaults;
     // Maps preference keys to a description of what they affect
     // Maps preference keys to a description of what they affect
     NSDictionary<NSString *, NSString *> *explorerToggles = @{
     NSDictionary<NSString *, NSString *> *explorerToggles = @{
-        kFLEXDefaultsHidePropertyIvarsKey:   @"Property-Backing Ivars",
-        kFLEXDefaultsHidePropertyMethodsKey: @"Property-Backing Methods",
-        kFLEXDefaultsHideMethodOverridesKey: @"Method Overrides",
+        kFLEXDefaultsHidePropertyIvarsKey:    @"Property-Backing Ivars",
+        kFLEXDefaultsHidePropertyMethodsKey:  @"Property-Backing Methods",
+        kFLEXDefaultsHideMethodOverridesKey:  @"Method Overrides",
+        kFLEXDefaultsHideVariablePreviewsKey: @"Variable Previews"
     };
     };
     
     
     // Maps the key of the action itself to a map of a description
     // Maps the key of the action itself to a map of a description
@@ -303,9 +300,10 @@
     //
     //
     // So keys that are hidden by default have NO mapped to "Show"
     // So keys that are hidden by default have NO mapped to "Show"
     NSDictionary<NSString *, NSDictionary *> *nextStateDescriptions = @{
     NSDictionary<NSString *, NSDictionary *> *nextStateDescriptions = @{
-        kFLEXDefaultsHidePropertyIvarsKey:   @{ @NO: @"Hide ", @YES: @"Show " },
-        kFLEXDefaultsHidePropertyMethodsKey: @{ @NO: @"Hide ", @YES: @"Show " },
-        kFLEXDefaultsHideMethodOverridesKey: @{ @NO: @"Show ", @YES: @"Hide " },
+        kFLEXDefaultsHidePropertyIvarsKey:    @{ @NO: @"Hide ", @YES: @"Show " },
+        kFLEXDefaultsHidePropertyMethodsKey:  @{ @NO: @"Hide ", @YES: @"Show " },
+        kFLEXDefaultsHideMethodOverridesKey:  @{ @NO: @"Show ", @YES: @"Hide " },
+        kFLEXDefaultsHideVariablePreviewsKey: @{ @NO: @"Hide ", @YES: @"Show " },
     };
     };
     
     
     [FLEXAlert makeSheet:^(FLEXAlert *make) {
     [FLEXAlert makeSheet:^(FLEXAlert *make) {

+ 2 - 2
Classes/ObjectExplorers/Sections/Shortcuts/FLEXShortcut.h

@@ -6,7 +6,7 @@
 //  Copyright © 2019 Flipboard. All rights reserved.
 //  Copyright © 2019 Flipboard. All rights reserved.
 //
 //
 
 
-#import <UIKit/UIKit.h>
+#import "FLEXObjectExplorer.h"
 
 
 NS_ASSUME_NONNULL_BEGIN
 NS_ASSUME_NONNULL_BEGIN
 
 
@@ -18,7 +18,7 @@ NS_ASSUME_NONNULL_BEGIN
 ///
 ///
 /// It is useful to make your own shortcuts to append/prepend
 /// It is useful to make your own shortcuts to append/prepend
 /// them to the existing list of shortcuts for a class.
 /// them to the existing list of shortcuts for a class.
-@protocol FLEXShortcut <NSObject>
+@protocol FLEXShortcut <FLEXObjectExplorerItem>
 
 
 - (nonnull  NSString *)titleWith:(id)object;
 - (nonnull  NSString *)titleWith:(id)object;
 - (nullable NSString *)subtitleWith:(id)object;
 - (nullable NSString *)subtitleWith:(id)object;

+ 37 - 2
Classes/ObjectExplorers/Sections/Shortcuts/FLEXShortcut.m

@@ -33,6 +33,7 @@
 @end
 @end
 
 
 @implementation FLEXShortcut
 @implementation FLEXShortcut
+@synthesize defaults = _defaults;
 
 
 + (id<FLEXShortcut>)shortcutFor:(id)item {
 + (id<FLEXShortcut>)shortcutFor:(id)item {
     if ([item conformsToProtocol:@protocol(FLEXShortcut)]) {
     if ([item conformsToProtocol:@protocol(FLEXShortcut)]) {
@@ -85,7 +86,7 @@
 
 
 - (NSString *)subtitleWith:(id)object {
 - (NSString *)subtitleWith:(id)object {
     if (self.metadataKind) {
     if (self.metadataKind) {
-        return [self.metadata previewWithTarget:object] ?: @"nil";
+        return [self.metadata previewWithTarget:object];
     }
     }
 
 
     // Item is probably a string; must return empty string since
     // Item is probably a string; must return empty string since
@@ -124,6 +125,32 @@
     return kFLEXMultilineCell;
     return kFLEXMultilineCell;
 }
 }
 
 
+#pragma mark FLEXObjectExplorerDefaults
+
+- (void)setDefaults:(FLEXObjectExplorerDefaults *)defaults {
+    _defaults = defaults;
+    
+    if (_metadataKind) {
+        self.metadata.defaults = defaults;
+    }
+}
+
+- (BOOL)isEditable {
+    if (_metadataKind) {
+        return self.metadata.isEditable;
+    }
+    
+    return NO;
+}
+
+- (BOOL)isCallable {
+    if (_metadataKind) {
+        return self.metadata.isCallable;
+    }
+    
+    return NO;
+}
+
 #pragma mark - Helpers
 #pragma mark - Helpers
 
 
 - (FLEXProperty *)property { return _item; }
 - (FLEXProperty *)property { return _item; }
@@ -145,6 +172,7 @@
 @end
 @end
 
 
 @implementation FLEXActionShortcut
 @implementation FLEXActionShortcut
+@synthesize defaults = _defaults;
 
 
 + (instancetype)title:(NSString *)title
 + (instancetype)title:(NSString *)title
              subtitle:(NSString *(^)(id))subtitle
              subtitle:(NSString *(^)(id))subtitle
@@ -186,7 +214,11 @@
 }
 }
 
 
 - (NSString *)subtitleWith:(id)object {
 - (NSString *)subtitleWith:(id)object {
-    return self.subtitleFuture(object);
+    if (self.defaults.wantsDynamicPreviews) {
+        return self.subtitleFuture(object);
+    }
+    
+    return nil;
 }
 }
 
 
 - (void (^)(UIViewController *))didSelectActionWith:(id)object {
 - (void (^)(UIViewController *))didSelectActionWith:(id)object {
@@ -216,4 +248,7 @@
     return nil;
     return nil;
 }
 }
 
 
+- (BOOL)isEditable { return NO; }
+- (BOOL)isCallable { return NO; }
+
 @end
 @end

+ 6 - 9
Classes/ObjectExplorers/Sections/Shortcuts/FLEXShortcutsSection.m

@@ -16,6 +16,7 @@
 #import "FLEXIvar.h"
 #import "FLEXIvar.h"
 #import "FLEXMethod.h"
 #import "FLEXMethod.h"
 #import "FLEXRuntime+UIKitHelpers.h"
 #import "FLEXRuntime+UIKitHelpers.h"
+#import "FLEXObjectExplorer.h"
 
 
 #pragma mark Private
 #pragma mark Private
 
 
@@ -86,6 +87,7 @@
             return [FLEXShortcut shortcutFor:obj];
             return [FLEXShortcut shortcutFor:obj];
         }];
         }];
         _numberOfLines = 1;
         _numberOfLines = 1;
+        
         // Populate titles and subtitles
         // Populate titles and subtitles
         [self reloadData];
         [self reloadData];
     }
     }
@@ -156,6 +158,8 @@
 }
 }
 
 
 - (void)reloadData {
 - (void)reloadData {
+    [FLEXObjectExplorer configureDefaultsForItems:self.allShortcuts];
+    
     // Generate all (sub)titles from shortcuts
     // Generate all (sub)titles from shortcuts
     if (self.allShortcuts) {
     if (self.allShortcuts) {
         self.allTitles = [self.allShortcuts flex_mapped:^id(FLEXShortcut *s, NSUInteger idx) {
         self.allTitles = [self.allShortcuts flex_mapped:^id(FLEXShortcut *s, NSUInteger idx) {
@@ -303,15 +307,8 @@ static RegistrationBuckets *mMethods = nil;
             classKey = class_getSuperclass(classKey);
             classKey = class_getSuperclass(classKey);
         }
         }
     }
     }
-
-    // .tag is used to cache whether the value of .isEditable;
-    // This could change at runtime so it is important that
-    // it is cached every time shortcuts are requeted and not
-    // just once at as shortcuts are initially registered
-    for (id<FLEXRuntimeMetadata> metadata in shortcuts) {
-        metadata.tag = metadata.isEditable ? @YES : nil;
-    }
-
+    
+    [FLEXObjectExplorer configureDefaultsForItems:shortcuts];
     return shortcuts;
     return shortcuts;
 }
 }
 
 

+ 1 - 1
Classes/ObjectExplorers/Sections/Shortcuts/FLEXViewControllerShortcuts.m

@@ -40,7 +40,7 @@
 
 
 + (instancetype)forObject:(UIViewController *)viewController {
 + (instancetype)forObject:(UIViewController *)viewController {
     BOOL (^vcIsInuse)(UIViewController *) = ^BOOL(UIViewController *controller) {
     BOOL (^vcIsInuse)(UIViewController *) = ^BOOL(UIViewController *controller) {
-        if (controller.view.window) {
+        if (controller.viewIfLoaded.window) {
             return YES;
             return YES;
         }
         }
 
 

+ 19 - 5
Classes/Utility/Categories/FLEXRuntime+UIKitHelpers.h

@@ -12,15 +12,25 @@
 #import "FLEXMethod.h"
 #import "FLEXMethod.h"
 #import "FLEXProtocol.h"
 #import "FLEXProtocol.h"
 
 
-@protocol FLEXRuntimeMetadata <NSObject>
-/// Used as the main title of the row
-- (NSString *)description;
-/// Used to compare metadata objects for uniqueness
-@property (nonatomic, readonly) NSString *name;
+@class FLEXObjectExplorerDefaults;
+
+/// Model objects of an object explorer screen adopt this
+/// protocol in order respond to user defaults changes 
+@protocol FLEXObjectExplorerItem <NSObject>
+/// Current explorer settings. Set when settings change.
+@property (nonatomic) FLEXObjectExplorerDefaults *defaults;
+
 /// YES for properties and ivars which surely support editing, NO for all methods.
 /// YES for properties and ivars which surely support editing, NO for all methods.
 @property (nonatomic, readonly) BOOL isEditable;
 @property (nonatomic, readonly) BOOL isEditable;
 /// NO for ivars, YES for supported methods and properties
 /// NO for ivars, YES for supported methods and properties
 @property (nonatomic, readonly) BOOL isCallable;
 @property (nonatomic, readonly) BOOL isCallable;
+@end
+
+@protocol FLEXRuntimeMetadata <FLEXObjectExplorerItem>
+/// Used as the main title of the row
+- (NSString *)description;
+/// Used to compare metadata objects for uniqueness
+@property (nonatomic, readonly) NSString *name;
 
 
 /// For internal use
 /// For internal use
 @property (nonatomic) id tag;
 @property (nonatomic) id tag;
@@ -76,3 +86,7 @@ typedef NS_ENUM(NSUInteger, FLEXStaticMetadataRowStyle) {
 + (NSArray<FLEXStaticMetadata *> *)classHierarchy:(NSArray<Class> *)classes;
 + (NSArray<FLEXStaticMetadata *> *)classHierarchy:(NSArray<Class> *)classes;
 
 
 @end
 @end
+
+
+/// This is assigned to the \c tag property of each metadata.
+

+ 28 - 8
Classes/Utility/Categories/FLEXRuntime+UIKitHelpers.m

@@ -18,8 +18,18 @@
 #import "NSArray+Functional.h"
 #import "NSArray+Functional.h"
 #import "NSString+FLEX.h"
 #import "NSString+FLEX.h"
 
 
+#define FLEXObjectExplorerDefaultsImpl \
+- (FLEXObjectExplorerDefaults *)defaults { \
+    return self.tag; \
+} \
+ \
+- (void)setDefaults:(FLEXObjectExplorerDefaults *)defaults { \
+    self.tag = defaults; \
+}
+
 #pragma mark FLEXProperty
 #pragma mark FLEXProperty
 @implementation FLEXProperty (UIKitHelpers)
 @implementation FLEXProperty (UIKitHelpers)
+FLEXObjectExplorerDefaultsImpl
 
 
 /// Decide whether to use potentialTarget or [potentialTarget class] to get or set property
 /// Decide whether to use potentialTarget or [potentialTarget class] to get or set property
 - (id)appropriateTargetForPropertyType:(id)potentialTarget {
 - (id)appropriateTargetForPropertyType:(id)potentialTarget {
@@ -67,11 +77,13 @@
 - (NSString *)previewWithTarget:(id)object {
 - (NSString *)previewWithTarget:(id)object {
     if (object_isClass(object) && !self.isClassProperty) {
     if (object_isClass(object) && !self.isClassProperty) {
         return self.attributes.fullDeclaration;
         return self.attributes.fullDeclaration;
-    } else {
+    } else if (self.defaults.wantsDynamicPreviews) {
         return [FLEXRuntimeUtility
         return [FLEXRuntimeUtility
             summaryForObject:[self currentValueWithTarget:object]
             summaryForObject:[self currentValueWithTarget:object]
         ];
         ];
     }
     }
+    
+    return nil;
 }
 }
 
 
 - (UIViewController *)viewerWithTarget:(id)object {
 - (UIViewController *)viewerWithTarget:(id)object {
@@ -94,7 +106,7 @@
     // We use .tag to store the cached value of .isEditable that is
     // We use .tag to store the cached value of .isEditable that is
     // initialized by FLEXObjectExplorer in -reloadMetada
     // initialized by FLEXObjectExplorer in -reloadMetada
     if ([self getPotentiallyUnboxedValue:targetForValueCheck]) {
     if ([self getPotentiallyUnboxedValue:targetForValueCheck]) {
-        if (self.tag) {
+        if (self.defaults.isEditable) {
             // Editable non-nil value, both
             // Editable non-nil value, both
             return UITableViewCellAccessoryDetailDisclosureButton;
             return UITableViewCellAccessoryDetailDisclosureButton;
         } else {
         } else {
@@ -102,7 +114,7 @@
             return UITableViewCellAccessoryDisclosureIndicator;
             return UITableViewCellAccessoryDisclosureIndicator;
         }
         }
     } else {
     } else {
-        if (self.tag) {
+        if (self.defaults.isEditable) {
             // Editable nil value, just (i)
             // Editable nil value, just (i)
             return UITableViewCellAccessoryDetailButton;
             return UITableViewCellAccessoryDetailButton;
         } else {
         } else {
@@ -177,6 +189,7 @@
 
 
 #pragma mark FLEXIvar
 #pragma mark FLEXIvar
 @implementation FLEXIvar (UIKitHelpers)
 @implementation FLEXIvar (UIKitHelpers)
+FLEXObjectExplorerDefaultsImpl
 
 
 - (BOOL)isEditable {
 - (BOOL)isEditable {
     const FLEXTypeEncoding *typeEncoding = self.typeEncoding.UTF8String;
     const FLEXTypeEncoding *typeEncoding = self.typeEncoding.UTF8String;
@@ -198,10 +211,13 @@
 - (NSString *)previewWithTarget:(id)object {
 - (NSString *)previewWithTarget:(id)object {
     if (object_isClass(object)) {
     if (object_isClass(object)) {
         return self.details;
         return self.details;
+    } else if (self.defaults.wantsDynamicPreviews) {
+        return [FLEXRuntimeUtility
+            summaryForObject:[self currentValueWithTarget:object]
+        ];
     }
     }
-    return [FLEXRuntimeUtility
-        summaryForObject:[self currentValueWithTarget:object]
-    ];
+    
+    return nil;
 }
 }
 
 
 - (UIViewController *)viewerWithTarget:(id)object {
 - (UIViewController *)viewerWithTarget:(id)object {
@@ -222,7 +238,7 @@
 
 
     // Could use .isEditable here, but we use .tag for speed since it is cached
     // Could use .isEditable here, but we use .tag for speed since it is cached
     if ([self getPotentiallyUnboxedValue:object]) {
     if ([self getPotentiallyUnboxedValue:object]) {
-        if (self.tag) {
+        if (self.defaults.isEditable) {
             // Editable non-nil value, both
             // Editable non-nil value, both
             return UITableViewCellAccessoryDetailDisclosureButton;
             return UITableViewCellAccessoryDetailDisclosureButton;
         } else {
         } else {
@@ -230,7 +246,7 @@
             return UITableViewCellAccessoryDisclosureIndicator;
             return UITableViewCellAccessoryDisclosureIndicator;
         }
         }
     } else {
     } else {
-        if (self.tag) {
+        if (self.defaults.isEditable) {
             // Editable nil value, just (i)
             // Editable nil value, just (i)
             return UITableViewCellAccessoryDetailButton;
             return UITableViewCellAccessoryDetailButton;
         } else {
         } else {
@@ -301,6 +317,7 @@
 
 
 #pragma mark FLEXMethod
 #pragma mark FLEXMethod
 @implementation FLEXMethodBase (UIKitHelpers)
 @implementation FLEXMethodBase (UIKitHelpers)
+FLEXObjectExplorerDefaultsImpl
 
 
 - (BOOL)isEditable {
 - (BOOL)isEditable {
     return NO;
     return NO;
@@ -402,6 +419,7 @@
 
 
 #pragma mark FLEXProtocol
 #pragma mark FLEXProtocol
 @implementation FLEXProtocol (UIKitHelpers)
 @implementation FLEXProtocol (UIKitHelpers)
+FLEXObjectExplorerDefaultsImpl
 
 
 - (BOOL)isEditable {
 - (BOOL)isEditable {
     return NO;
     return NO;
@@ -475,6 +493,8 @@
 @synthesize name = _name;
 @synthesize name = _name;
 @synthesize tag = _tag;
 @synthesize tag = _tag;
 
 
+FLEXObjectExplorerDefaultsImpl
+
 + (NSArray<FLEXStaticMetadata *> *)classHierarchy:(NSArray<Class> *)classes {
 + (NSArray<FLEXStaticMetadata *> *)classHierarchy:(NSArray<Class> *)classes {
     return [classes flex_mapped:^id(Class cls, NSUInteger idx) {
     return [classes flex_mapped:^id(Class cls, NSUInteger idx) {
         return [FLEXStaticMetadata_Class withClass:cls];
         return [FLEXStaticMetadata_Class withClass:cls];

+ 3 - 0
Classes/Utility/Categories/NSUserDefaults+FLEX.h

@@ -14,6 +14,7 @@ extern NSString * const kFLEXDefaultsiOSPersistentOSLogKey;
 extern NSString * const kFLEXDefaultsHidePropertyIvarsKey;
 extern NSString * const kFLEXDefaultsHidePropertyIvarsKey;
 extern NSString * const kFLEXDefaultsHidePropertyMethodsKey;
 extern NSString * const kFLEXDefaultsHidePropertyMethodsKey;
 extern NSString * const kFLEXDefaultsHideMethodOverridesKey;
 extern NSString * const kFLEXDefaultsHideMethodOverridesKey;
+extern NSString * const kFLEXDefaultsHideVariablePreviewsKey;
 extern NSString * const kFLEXDefaultsNetworkHostBlacklistKey;
 extern NSString * const kFLEXDefaultsNetworkHostBlacklistKey;
 
 
 @interface NSUserDefaults (FLEX)
 @interface NSUserDefaults (FLEX)
@@ -31,6 +32,8 @@ extern NSString * const kFLEXDefaultsNetworkHostBlacklistKey;
 @property (nonatomic) BOOL flex_explorerHidesPropertyMethods;
 @property (nonatomic) BOOL flex_explorerHidesPropertyMethods;
 /// NO by default
 /// NO by default
 @property (nonatomic) BOOL flex_explorerShowsMethodOverrides;
 @property (nonatomic) BOOL flex_explorerShowsMethodOverrides;
+/// NO by default
+@property (nonatomic) BOOL flex_explorerHidesVariablePreviews;
 
 
 // Not actually stored in defaults, but written to a file
 // Not actually stored in defaults, but written to a file
 @property (nonatomic) NSArray<NSString *> *flex_networkHostBlacklist;
 @property (nonatomic) NSArray<NSString *> *flex_networkHostBlacklist;

+ 13 - 0
Classes/Utility/Categories/NSUserDefaults+FLEX.m

@@ -13,6 +13,7 @@ NSString * const kFLEXDefaultsiOSPersistentOSLogKey = @"com.flipborad.flex.enabl
 NSString * const kFLEXDefaultsHidePropertyIvarsKey = @"com.flipboard.FLEX.hide_property_ivars";
 NSString * const kFLEXDefaultsHidePropertyIvarsKey = @"com.flipboard.FLEX.hide_property_ivars";
 NSString * const kFLEXDefaultsHidePropertyMethodsKey = @"com.flipboard.FLEX.hide_property_methods";
 NSString * const kFLEXDefaultsHidePropertyMethodsKey = @"com.flipboard.FLEX.hide_property_methods";
 NSString * const kFLEXDefaultsHideMethodOverridesKey = @"com.flipboard.FLEX.hide_method_overrides";
 NSString * const kFLEXDefaultsHideMethodOverridesKey = @"com.flipboard.FLEX.hide_method_overrides";
+NSString * const kFLEXDefaultsHideVariablePreviewsKey = @"com.flipboard.FLEX.hide_variable_previews";
 NSString * const kFLEXDefaultsNetworkHostBlacklistKey = @"com.flipboard.FLEX.network_host_blacklist";
 NSString * const kFLEXDefaultsNetworkHostBlacklistKey = @"com.flipboard.FLEX.network_host_blacklist";
 
 
 #define FLEXDefaultsPathForFile(name) ({ \
 #define FLEXDefaultsPathForFile(name) ({ \
@@ -100,6 +101,18 @@ NSString * const kFLEXDefaultsNetworkHostBlacklistKey = @"com.flipboard.FLEX.net
     ];
     ];
 }
 }
 
 
+- (BOOL)flex_explorerHidesVariablePreviews {
+    return [self boolForKey:kFLEXDefaultsHideVariablePreviewsKey];
+}
+
+- (void)setFlex_explorerHidesVariablePreviews:(BOOL)hide {
+    [self setBool:hide forKey:kFLEXDefaultsHideVariablePreviewsKey];
+    [NSNotificationCenter.defaultCenter
+        postNotificationName:kFLEXDefaultsHideVariablePreviewsKey
+        object:nil
+    ];
+}
+
 - (NSArray<NSString *> *)flex_networkHostBlacklist {
 - (NSArray<NSString *> *)flex_networkHostBlacklist {
     return [NSArray arrayWithContentsOfFile:[
     return [NSArray arrayWithContentsOfFile:[
         self flex_defaultsPathForFile:kFLEXDefaultsNetworkHostBlacklistKey
         self flex_defaultsPathForFile:kFLEXDefaultsNetworkHostBlacklistKey