Sfoglia il codice sorgente

Adopt FLEXExplorerSection additions

# Conflicts:
#	Classes/ObjectExplorers/Controllers/FLEXObjectExplorerViewController.m

# Conflicts:
#	Classes/ObjectExplorers/FLEXObjectExplorerFactory.m
Tanner Bennett 6 anni fa
parent
commit
aa5b9d4e7f

+ 26 - 45
Classes/ObjectExplorers/Controllers/FLEXObjectExplorerViewController.h

@@ -11,63 +11,44 @@
 #endif
 
 #import "FLEXTableViewController.h"
+#import "FLEXObjectExplorer.h"
+@class FLEXExplorerSection;
 
-typedef NS_ENUM(NSUInteger, FLEXObjectExplorerSection) {
-    FLEXObjectExplorerSectionDescription,
-    FLEXObjectExplorerSectionCustom,
-    FLEXObjectExplorerSectionProperties,
-    FLEXObjectExplorerSectionIvars,
-    FLEXObjectExplorerSectionMethods,
-    FLEXObjectExplorerSectionClassMethods,
-    FLEXObjectExplorerSectionSuperclasses,
-    FLEXObjectExplorerSectionReferencingInstances
-};
+NS_ASSUME_NONNULL_BEGIN
 
+/// A class that displays information about an object or class.
+///
+/// The explorer view controller uses \c FLEXObjectExplorer to provide a description
+/// of the object and list it's properties, ivars, methods, and it's superclasses.
+/// Below the description and before properties, some shortcuts will be displayed
+/// for certain classes like UIViews. At very bottom, there is an option to view
+/// a list of other objects found to be referencing the object being explored.
 @interface FLEXObjectExplorerViewController : FLEXTableViewController
 
-@property (nonatomic) id object;
+/// Uses the default \c FLEXShortcutsSection for this object as a custom section.
++ (instancetype)exploringObject:(id)objectOrClass;
+/// No custom section unless you provide one.
++ (instancetype)exploringObject:(id)objectOrClass customSection:(nullable FLEXExplorerSection *)customSection;
 
-// Subclasses can override the methods below to provide data in a custom section.
-// The subclass should provide an array of "row cookies" to allow retrieval of individual row data later on.
-// The objects in the rowCookies array will be used to call the row title, subtitle, etc methods to construct the rows.
-// The cookies approach is used here because we may filter the visible rows based on the search text entered by the user.
-- (NSString *)customSectionTitle;
-- (NSArray *)customSectionRowCookies;
-- (NSString *)customSectionTitleForRowCookie:(id)rowCookie;
-- (NSString *)customSectionSubtitleForRowCookie:(id)rowCookie;
-- (BOOL)customSectionCanDrillIntoRowWithCookie:(id)rowCookie;
-- (UIViewController *)customSectionDrillInViewControllerForRowCookie:(id)rowCookie;
-- (UIView *)customViewForRowCookie:(id)rowCookie;
+/// The object being explored, which may be an instance of a class or a class itself.
+@property (nonatomic, readonly) id object;
+/// This object provides the object's metadata for the explorer view controller.
+@property (nonatomic, readonly) FLEXObjectExplorer *explorer;
 
-// More subclass configuration hooks.
+/// Called once to initialize the list of section objects.
+///
+/// Subclasses can override this to add, remove, or rearrange sections of the explorer.
+- (NSArray<FLEXExplorerSection *> *)makeSections;
 
 /// Whether to allow showing/drilling in to current values for ivars and properties. Default is YES.
-- (BOOL)canHaveInstanceState;
+@property (nonatomic, readonly) BOOL canHaveInstanceState;
 
 /// Whether to allow drilling in to method calling interfaces for instance methods. Default is YES.
-- (BOOL)canCallInstanceMethods;
+@property (nonatomic, readonly) BOOL canCallInstanceMethods;
 
 /// If the custom section data makes the description redundant, subclasses can choose to hide it. Default is YES.
-- (BOOL)shouldShowDescription;
-
-/// Subclasses can reorder/change which sections can display directly by overriding this method.
-- (NSArray *)possibleExplorerSections;
-
-/// Subclasses can override to provide a more useful description
-- (NSString *)displayedObjectDescription;
+@property (nonatomic, readonly) BOOL shouldShowDescription;
 
 @end
 
-@interface FLEXObjectExplorerViewController (Shortcuts)
-
-/// @brief Names of properties to supply as shortcuts. If this array is empty, no shortcuts are displayed.
-///
-/// @discussion Populating this array in a subclass will make FLEXObjectExplorerViewController show a custom
-/// section with row titles like "@property NSString *foo" and subtitles with their values.
-/// customSectionRowCookies will return this array. Every row in the section is drillable by default.
-///
-/// For an example on how to use the default behavior provided or to override it,
-/// see FLEXViewExplorerViewController
-- (NSArray<NSString *> *)shortcutPropertyNames;
-
-@end
+NS_ASSUME_NONNULL_END

File diff suppressed because it is too large
+ 205 - 879
Classes/ObjectExplorers/Controllers/FLEXObjectExplorerViewController.m


+ 5 - 0
Classes/ObjectExplorers/FLEXObjectExplorerFactory.h

@@ -18,4 +18,9 @@
 
 + (FLEXObjectExplorerViewController *)explorerViewControllerForObject:(id)object;
 
+/// Register a specific explorer view controller class to be used when exploring
+/// an object of a specific class. Calls will overwrite existing registrations.
+/// Sections must be initialized using \c forObject: like
++ (void)registerExplorerSection:(Class)sectionClass forClass:(Class)objectClass;
+
 @end

+ 53 - 49
Classes/ObjectExplorers/FLEXObjectExplorerFactory.m

@@ -7,66 +7,70 @@
 //
 
 #import "FLEXObjectExplorerFactory.h"
-#import "FLEXObjectExplorerViewController.h"
-#import "FLEXArrayExplorerViewController.h"
-#import "FLEXSetExplorerViewController.h"
-#import "FLEXDictionaryExplorerViewController.h"
-#import "FLEXDefaultsExplorerViewController.h"
-#import "FLEXViewControllerExplorerViewController.h"
-#import "FLEXViewExplorerViewController.h"
-#import "FLEXImageExplorerViewController.h"
-#import "FLEXClassExplorerViewController.h"
-#import "FLEXLayerExplorerViewController.h"
-#import "FLEXColorExplorerViewController.h"
-#import "FLEXBundleExplorerViewController.h"
 #import "FLEXGlobalsTableViewController.h"
 #import "FLEXAlert.h"
+#import "FLEXClassShortcuts.h"
+#import "FLEXViewShortcuts.h"
+#import "FLEXImageShortcuts.h"
+#import "FLEXLayerShortcuts.h"
+#import "FLEXColorPreviewSection.h"
+#import "FLEXDefaultsContentSection.h"
+#import "FLEXBundleShortcuts.h"
 #import <objc/runtime.h>
 
 @implementation FLEXObjectExplorerFactory
+static NSMutableDictionary<Class, Class> *classesToRegisteredSections = nil;
+
++ (void)initialize
+{
+    if (self == [FLEXObjectExplorerFactory class]) {
+        #define ClassKey(name) (Class<NSCopying>)[name class]
+        classesToRegisteredSections = [NSMutableDictionary dictionaryWithDictionary:@{
+            ClassKey(NSArray)          : [FLEXCollectionContentSection class],
+            ClassKey(NSSet)            : [FLEXCollectionContentSection class],
+            ClassKey(NSDictionary)     : [FLEXCollectionContentSection class],
+            ClassKey(NSUserDefaults)   : [FLEXDefaultsContentSection class],
+//            ClassKey(UIViewController) : [FLEXViewControllerExplorerViewController class],
+            ClassKey(UIView)           : [FLEXViewShortcuts class],
+            ClassKey(UIImage)          : [FLEXImageShortcuts class],
+            ClassKey(CALayer)          : [FLEXLayerShortcuts class],
+            ClassKey(UIColor)          : [FLEXColorPreviewSection class],
+            ClassKey(NSBundle)         : [FLEXBundleShortcuts class],
+        }];
+        #undef ClassKey
+    }
+}
 
 + (FLEXObjectExplorerViewController *)explorerViewControllerForObject:(id)object
 {
-    // Bail for nil object. We can't explore nil.
+    // Can't explore nil
     if (!object) {
         return nil;
     }
-    
-    static NSDictionary<NSString *, Class> *explorerSubclassesForObjectTypeStrings = nil;
-    static dispatch_once_t once;
-    dispatch_once(&once, ^{
-        explorerSubclassesForObjectTypeStrings = @{NSStringFromClass([NSArray class])          : [FLEXArrayExplorerViewController class],
-                                                   NSStringFromClass([NSSet class])            : [FLEXSetExplorerViewController class],
-                                                   NSStringFromClass([NSDictionary class])     : [FLEXDictionaryExplorerViewController class],
-                                                   NSStringFromClass([NSUserDefaults class])   : [FLEXDefaultsExplorerViewController class],
-                                                   NSStringFromClass([UIViewController class]) : [FLEXViewControllerExplorerViewController class],
-                                                   NSStringFromClass([UIView class])           : [FLEXViewExplorerViewController class],
-                                                   NSStringFromClass([UIImage class])          : [FLEXImageExplorerViewController class],
-                                                   NSStringFromClass([CALayer class])          : [FLEXLayerExplorerViewController class],
-                                                   NSStringFromClass([UIColor class])          : [FLEXColorExplorerViewController class],
-                                                   NSStringFromClass([NSBundle class])         : [FLEXBundleExplorerViewController class],
-                                                   };
-    });
-    
-    Class explorerClass = nil;
-    BOOL objectIsClass = class_isMetaClass(object_getClass(object));
-    if (objectIsClass) {
-        explorerClass = [FLEXClassExplorerViewController class];
-    } else {
-        explorerClass = [FLEXObjectExplorerViewController class];
-        for (NSString *objectTypeString in explorerSubclassesForObjectTypeStrings) {
-            Class objectClass = NSClassFromString(objectTypeString);
-            if ([object isKindOfClass:objectClass]) {
-                explorerClass = explorerSubclassesForObjectTypeStrings[objectTypeString];
-                break;
-            }
-        }
-    }
-    
-    FLEXObjectExplorerViewController *explorerViewController = [explorerClass new];
-    explorerViewController.object = object;
-    
-    return explorerViewController;
+
+    // If we're given an object, this will look up it's class hierarchy
+    // until it finds a registration. This will work for KVC classes,
+    // since they are children of the original class, and not siblings.
+    // If we are given an object, object_getClass will return a metaclass,
+    // and the same thing will happen. FLEXClassShortcuts is the default
+    // shortcut section for NSObject.
+    //
+    // TODO: rename it to FLEXNSObjectShortcuts or something?
+    Class sectionClass = nil;
+    Class cls = object_getClass(object);
+    do {
+        sectionClass = classesToRegisteredSections[(Class<NSCopying>)cls];
+    } while (!sectionClass && (cls = [cls superclass]));
+
+    return [FLEXObjectExplorerViewController
+        exploringObject:object
+        customSection:[sectionClass forObject:object]
+    ];
+}
+
++ (void)registerExplorerSection:(Class)explorerClass forClass:(Class)objectClass
+{
+    classesToRegisteredSections[(Class<NSCopying>)objectClass] = explorerClass;
 }
 
 #pragma mark - FLEXGlobalsEntry