Преглед изворни кода

Reorganize project structure part 2

Rename FLEXExplorerSection → FLEXTableViewSection
Tanner Bennett пре 6 година
родитељ
комит
30ce841030

+ 2 - 2
Classes/ObjectExplorers/Sections/FLEXSingleRowSection.h

@@ -6,14 +6,14 @@
 //  Copyright © 2019 Flipboard. All rights reserved.
 //
 
-#import "FLEXExplorerSection.h"
+#import "FLEXTableViewSection.h"
 
 /// A section providing a specific single row.
 ///
 /// You may optionally provide a view controller to push when the row
 /// is selected, or an action to perform when it is selected.
 /// Which one is used first is up to the table view data source.
-@interface FLEXSingleRowSection : FLEXExplorerSection
+@interface FLEXSingleRowSection : FLEXTableViewSection
 
 /// @param reuseIdentifier if nil, kFLEXDefaultCell is used.
 + (instancetype)title:(NSString *)sectionTitle

Classes/ObjectExplorers/Sections/FLEXSingleRowSection.m → Classes/Core/FLEXSingleRowSection.m


+ 25 - 31
Classes/ObjectExplorers/Sections/FLEXExplorerSection.h

@@ -1,24 +1,29 @@
 //
-//  FLEXExplorerSection.h
+//  FLEXTableViewSection.h
 //  FLEX
 //
-//  Created by Tanner Bennett on 8/28/19.
-//  Copyright © 2019 Flipboard. All rights reserved.
+//  Created by Tanner on 1/29/20.
+//  Copyright © 2020 Flipboard. All rights reserved.
 //
 
-#import <UIKit/UIKit.h>
 #import "FLEXUtility.h"
 @class FLEXTableView;
 
-#pragma mark FLEXExplorerSection
+NS_ASSUME_NONNULL_BEGIN
 
-/// An abstract base class for custom object explorer sections.
-@interface FLEXExplorerSection : NSObject
+#pragma mark FLEXTableViewSection
+
+/// An abstract base class for table view sections.
+///
+/// Many properties or methods here return nil or some logical equivalent by default.
+/// Even so, most of the methods with defaults are intended to be overriden by subclasses.
+/// Some methods are not implemented at all and MUST be implemented by a subclass.
+@interface FLEXTableViewSection : NSObject
 
 #pragma mark - Data
 
-/// A title to be displayed for the custom section. Subclasses must override.
-@property (nonatomic, readonly) NSString *title;
+/// A title to be displayed for the custom section. Subclasses may override.
+@property (nonatomic, readonly, nullable) NSString *title;
 /// The number of rows in this section.
 /// This should not change until \c filterText is changed or \c reloadData is called.
 @property (nonatomic, readonly) NSInteger numberOfRows;
@@ -26,12 +31,12 @@
 /// Subclasses \e may override this as necessary, but are not required to.
 /// See \c FLEXTableView.h for more information.
 /// @return nil by default.
-@property (nonatomic, readonly) NSDictionary<NSString *, Class> *cellRegistrationMapping;
+@property (nonatomic, readonly, nullable) NSDictionary<NSString *, Class> *cellRegistrationMapping;
 
 /// The section should filter itself based on the contents of this property
 /// as it is set. If it is set to nil or an empty string, it should not filter.
 /// Subclasses should override or observe this property and react to changes.
-@property (nonatomic) NSString *filterText;
+@property (nonatomic, nullable) NSString *filterText;
 
 /// Provides an avenue for the section to change the number of rows.
 /// This is called before reloading the table view itself.
@@ -52,25 +57,25 @@
 /// @return This returns \c nil if no view controller is provided by
 /// \c viewControllerToPushForRow: — otherwise it pushes that view controller
 /// onto \c host.navigationController
-- (void(^)(UIViewController *host))didSelectRowAction:(NSInteger)row;
+- (nullable void(^)(UIViewController *host))didSelectRowAction:(NSInteger)row;
 
 /// A view controller to display when the row is selected, if the row
 /// supports being selected as indicated by \c canSelectRow:. Subclasses
 /// must implement this in accordance with how they implement \c canSelectRow:
 /// if they do not implement \c didSelectRowAction:
 /// @return \c nil by default
-- (UIViewController *)viewControllerToPushForRow:(NSInteger)row;
+- (nullable UIViewController *)viewControllerToPushForRow:(NSInteger)row;
 
 /// Called when the accessory view's detail button is pressed.
 /// @return \c nil by default.
-- (void(^)(UIViewController *host))didPressInfoButtonAction:(NSInteger)row;
+- (nullable void(^)(UIViewController *host))didPressInfoButtonAction:(NSInteger)row;
 
 #pragma mark - Context Menus
 #if FLEX_AT_LEAST_IOS13_SDK
 
 /// By default, this is the title of the row.
 /// @return The title of the context menu, if any.
-- (NSString *)menuTitleForRow:(NSInteger)row API_AVAILABLE(ios(13.0));
+- (nullable NSString *)menuTitleForRow:(NSInteger)row API_AVAILABLE(ios(13.0));
 /// Protected, not intended for public use. \c menuTitleForRow:
 /// already includes the value returned from this method.
 /// 
@@ -79,13 +84,13 @@
 - (NSString *)menuSubtitleForRow:(NSInteger)row API_AVAILABLE(ios(13.0));
 /// The context menu items, if any. Subclasses may override.
 /// By default, only inludes items for \c copyMenuItemsForRow:.
-- (NSArray<UIMenuElement *> *)menuItemsForRow:(NSInteger)row sender:(UIViewController *)sender API_AVAILABLE(ios(13.0));
+- (nullable NSArray<UIMenuElement *> *)menuItemsForRow:(NSInteger)row sender:(UIViewController *)sender API_AVAILABLE(ios(13.0));
 /// Subclasses may override to return a list of copiable items.
 /// 
 /// Every two elements in the list compose a key-value pair, where the key
 /// should be a description of what will be copied, and the values should be
 /// the strings to copy. Return an empty string as a value to show a disabled action.
-- (NSArray<NSString *> *)copyMenuItemsForRow:(NSInteger)row API_AVAILABLE(ios(13.0));
+- (nullable NSArray<NSString *> *)copyMenuItemsForRow:(NSInteger)row API_AVAILABLE(ios(13.0));
 #endif
 
 #pragma mark - Cell Configuration
@@ -104,22 +109,11 @@
 
 /// For use by whatever view controller uses your section. Not required.
 /// @return An optional title.
-- (NSString *)titleForRow:(NSInteger)row;
+- (nullable NSString *)titleForRow:(NSInteger)row;
 /// For use by whatever view controller uses your section. Not required.
 /// @return An optional subtitle.
-- (NSString *)subtitleForRow:(NSInteger)row;
+- (nullable NSString *)subtitleForRow:(NSInteger)row;
 
 @end
 
-
-#pragma mark - FLEXObjectInfoSection
-
-/// \c FLEXExplorerSection itself doesn't need to know about the object being explored.
-/// Subclasses might need this info to provide useful information about the object. Instead
-/// of adding an abstract class to the class hierarchy, subclasses can conform to this protocol
-/// to indicate that the only info they need to be initialized is the object being explored.
-@protocol FLEXObjectInfoSection <NSObject>
-
-+ (instancetype)forObject:(id)object;
-
-@end
+NS_ASSUME_NONNULL_END

+ 5 - 5
Classes/ObjectExplorers/Sections/FLEXExplorerSection.m

@@ -1,19 +1,19 @@
 //
-//  FLEXExplorerSection.m
+//  FLEXTableViewSection.m
 //  FLEX
 //
-//  Created by Tanner Bennett on 8/28/19.
-//  Copyright © 2019 Flipboard. All rights reserved.
+//  Created by Tanner on 1/29/20.
+//  Copyright © 2020 Flipboard. All rights reserved.
 //
 
-#import "FLEXExplorerSection.h"
+#import "FLEXTableViewSection.h"
 #import "FLEXTableView.h"
 #import "UIMenu+FLEX.h"
 
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wincomplete-implementation"
 
-@implementation FLEXExplorerSection
+@implementation FLEXTableViewSection
 
 - (void)reloadData { }
 

+ 4 - 6
Classes/Editing/FLEXVariableEditorViewController.m

@@ -17,11 +17,8 @@
 #import "FLEXObjectExplorerViewController.h"
 
 @interface FLEXVariableEditorViewController () <UIScrollViewDelegate>
-
 @property (nonatomic) UIScrollView *scrollView;
-
-@property (nonatomic, readwrite) id target;
-
+@property (nonatomic) id target;
 @end
 
 @implementation FLEXVariableEditorViewController
@@ -89,7 +86,7 @@
 {
     [super viewDidLoad];
     
-    self.view.backgroundColor = [FLEXColor scrollViewBackgroundColor];
+    self.view.backgroundColor = FLEXColor.scrollViewBackgroundColor;
     
     self.scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
     self.scrollView.backgroundColor = self.view.backgroundColor;
@@ -131,7 +128,8 @@
     [self.fieldEditorView endEditing:YES];
 }
 
-- (void)exploreObjectOrPopViewController:(id)objectOrNil {
+- (void)exploreObjectOrPopViewController:(id)objectOrNil
+{
     if (objectOrNil) {
         // For non-nil (or void) return types, push an explorer view controller to display the object
         FLEXObjectExplorerViewController *explorerViewController = [FLEXObjectExplorerFactory explorerViewControllerForObject:objectOrNil];

+ 3 - 3
Classes/ObjectExplorers/FLEXObjectExplorerViewController.h

@@ -12,7 +12,7 @@
 
 #import "FLEXTableViewController.h"
 #import "FLEXObjectExplorer.h"
-@class FLEXExplorerSection;
+@class FLEXTableViewSection;
 
 NS_ASSUME_NONNULL_BEGIN
 
@@ -28,7 +28,7 @@ NS_ASSUME_NONNULL_BEGIN
 /// 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;
++ (instancetype)exploringObject:(id)objectOrClass customSection:(nullable FLEXTableViewSection *)customSection;
 
 /// The object being explored, which may be an instance of a class or a class itself.
 @property (nonatomic, readonly) id object;
@@ -38,7 +38,7 @@ NS_ASSUME_NONNULL_BEGIN
 /// 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;
+- (NSArray<FLEXTableViewSection *> *)makeSections;
 
 /// Whether to allow showing/drilling in to current values for ivars and properties. Default is YES.
 @property (nonatomic, readonly) BOOL canHaveInstanceState;

+ 17 - 17
Classes/ObjectExplorers/FLEXObjectExplorerViewController.m

@@ -27,11 +27,11 @@
 
 @property (nonatomic, copy) NSString *filterText;
 /// Every section in the table view, regardless of whether or not a section is empty.
-@property (nonatomic, readonly) NSArray<FLEXExplorerSection *> *allSections;
+@property (nonatomic, readonly) NSArray<FLEXTableViewSection *> *allSections;
 /// Only displayed sections of the table view; empty sections are purged from this array.
-@property (nonatomic) NSArray<FLEXExplorerSection *> *sections;
+@property (nonatomic) NSArray<FLEXTableViewSection *> *sections;
 @property (nonatomic, readonly) FLEXSingleRowSection *descriptionSection;
-@property (nonatomic, readonly) FLEXExplorerSection *customSection;
+@property (nonatomic, readonly) FLEXTableViewSection *customSection;
 @property (nonatomic) NSIndexSet *customSectionVisibleIndexes;
 
 @end
@@ -45,7 +45,7 @@
     return [self exploringObject:target customSection:[FLEXShortcutsSection forObject:target]];
 }
 
-+ (instancetype)exploringObject:(id)target customSection:(FLEXExplorerSection *)section
++ (instancetype)exploringObject:(id)target customSection:(FLEXTableViewSection *)section
 {
     return [[self alloc]
         initWithObject:target
@@ -56,7 +56,7 @@
 
 - (id)initWithObject:(id)target
             explorer:(__kindof FLEXObjectExplorer *)explorer
-       customSection:(FLEXExplorerSection *)customSection
+       customSection:(FLEXTableViewSection *)customSection
 {
     NSParameterAssert(target);
     
@@ -80,7 +80,7 @@
     self.tableView = tableView;
 
     // Register cell classes
-    for (FLEXExplorerSection *section in self.allSections) {
+    for (FLEXTableViewSection *section in self.allSections) {
         if (section.cellRegistrationMapping) {
             [tableView registerCells:section.cellRegistrationMapping];
         }
@@ -155,7 +155,7 @@
     [self.refreshControl endRefreshing];
 }
 
-- (NSArray<FLEXExplorerSection *> *)makeSections
+- (NSArray<FLEXTableViewSection *> *)makeSections
 {
     FLEXObjectExplorer *explorer = self.explorer;
     
@@ -208,9 +208,9 @@
     return sections.copy;
 }
 
-- (NSArray<FLEXExplorerSection *> *)nonemptySections
+- (NSArray<FLEXTableViewSection *> *)nonemptySections
 {
-    return [self.allSections flex_filtered:^BOOL(FLEXExplorerSection *section, NSUInteger idx) {
+    return [self.allSections flex_filtered:^BOOL(FLEXTableViewSection *section, NSUInteger idx) {
         return section.numberOfRows > 0;
     }];
 }
@@ -265,14 +265,14 @@
     self.filterText = newText;
 
     // Sections will adjust data based on this property
-    for (FLEXExplorerSection *section in self.allSections) {
+    for (FLEXTableViewSection *section in self.allSections) {
         section.filterText = newText;
     }
 
     // Check to see if class scope changed, update accordingly
     if (self.explorer.classScope != self.selectedScope) {
         self.explorer.classScope = self.selectedScope;
-        for (FLEXExplorerSection *section in self.allSections) {
+        for (FLEXTableViewSection *section in self.allSections) {
             [section reloadData];
         }
     }
@@ -294,7 +294,7 @@
     [self.explorer reloadMetadata];
 
     // Reload sections
-    for (FLEXExplorerSection *section in self.allSections) {
+    for (FLEXTableViewSection *section in self.allSections) {
         [section reloadData];
     }
 
@@ -337,7 +337,7 @@
 {
     // For the description section, we want that nice slim/snug looking row.
     // Other rows use the automatic size.
-    FLEXExplorerSection *section = self.sections[indexPath.section];
+    FLEXTableViewSection *section = self.sections[indexPath.section];
     
     if (section == self.descriptionSection) {
         NSAttributedString *attributedText = [[NSAttributedString alloc]
@@ -357,7 +357,7 @@
 }
 
 - (NSArray<NSString *> *)sectionIndexTitlesForTableView:(UITableView *)tableView {
-    return [self.sections flex_mapped:^id(FLEXExplorerSection *obj, NSUInteger idx) {
+    return [self.sections flex_mapped:^id(FLEXTableViewSection *obj, NSUInteger idx) {
         return @"⦁";
     }];
 }
@@ -372,7 +372,7 @@
 
 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
 {
-    FLEXExplorerSection *section = self.sections[indexPath.section];
+    FLEXTableViewSection *section = self.sections[indexPath.section];
 
     void (^action)(UIViewController *) = [section didSelectRowAction:indexPath.row];
     UIViewController *details = [section viewControllerToPushForRow:indexPath.row];
@@ -418,7 +418,7 @@
 #if FLEX_AT_LEAST_IOS13_SDK
 
 - (UIContextMenuConfiguration *)tableView:(UITableView *)tableView contextMenuConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath point:(CGPoint)point __IOS_AVAILABLE(13.0) {
-    FLEXExplorerSection *section = self.sections[indexPath.section];
+    FLEXTableViewSection *section = self.sections[indexPath.section];
     NSString *title = [section menuTitleForRow:indexPath.row];
     NSArray<UIMenuElement *> *menuItems = [section menuItemsForRow:indexPath.row sender:self];
     
@@ -450,7 +450,7 @@
 
 - (void)copy:(NSIndexPath *)indexPath
 {
-    FLEXExplorerSection *section = self.sections[indexPath.section];
+    FLEXTableViewSection *section = self.sections[indexPath.section];
     UIPasteboard.generalPasteboard.string = ({
         NSString *copy = [section titleForRow:indexPath.row];
         NSString *subtitle = [section subtitleForRow:indexPath.row];

+ 3 - 2
Classes/ObjectExplorers/Sections/FLEXCollectionContentSection.h

@@ -6,7 +6,8 @@
 //  Copyright © 2019 Flipboard. All rights reserved.
 //
 
-#import "FLEXExplorerSection.h"
+#import "FLEXTableViewSection.h"
+#import "FLEXObjectInfoSection.h"
 @class FLEXCollectionContentSection;
 @protocol FLEXCollection;
 
@@ -45,7 +46,7 @@ typedef id<FLEXCollection>(^FLEXCollectionContentFuture)(__kindof FLEXCollection
 /// A custom section for viewing collection elements.
 ///
 /// Tapping on a row pushes an object explorer for that element.
-@interface FLEXCollectionContentSection : FLEXExplorerSection <FLEXObjectInfoSection>
+@interface FLEXCollectionContentSection : FLEXTableViewSection <FLEXObjectInfoSection>
 
 + (instancetype)forCollection:(id<FLEXCollection>)collection;
 /// The future given should be safe to call more than once.

+ 1 - 0
Classes/ObjectExplorers/Sections/FLEXColorPreviewSection.h

@@ -7,6 +7,7 @@
 //
 
 #import "FLEXSingleRowSection.h"
+#import "FLEXObjectInfoSection.h"
 
 @interface FLEXColorPreviewSection : FLEXSingleRowSection <FLEXObjectInfoSection>
 

+ 1 - 0
Classes/ObjectExplorers/Sections/FLEXDefaultsContentSection.h

@@ -7,6 +7,7 @@
 //
 
 #import "FLEXCollectionContentSection.h"
+#import "FLEXObjectInfoSection.h"
 
 @interface FLEXDefaultsContentSection : FLEXCollectionContentSection <FLEXObjectInfoSection>
 

+ 2 - 2
Classes/ObjectExplorers/Sections/FLEXMetadataSection.h

@@ -6,7 +6,7 @@
 //  Copyright © 2019 Flipboard. All rights reserved.
 //
 
-#import "FLEXExplorerSection.h"
+#import "FLEXTableViewSection.h"
 #import "FLEXObjectExplorer.h"
 
 typedef NS_ENUM(NSUInteger, FLEXMetadataKind) {
@@ -22,7 +22,7 @@ typedef NS_ENUM(NSUInteger, FLEXMetadataKind) {
 
 /// This section is used for displaying ObjC runtime metadata
 /// about a class or object, such as listing methods, properties, etc.
-@interface FLEXMetadataSection : FLEXExplorerSection
+@interface FLEXMetadataSection : FLEXTableViewSection
 
 + (instancetype)explorer:(FLEXObjectExplorer *)explorer kind:(FLEXMetadataKind)metadataKind;
 

+ 19 - 0
Classes/ObjectExplorers/Sections/FLEXObjectInfoSection.h

@@ -0,0 +1,19 @@
+//
+//  FLEXObjectInfoSection.h
+//  FLEX
+//
+//  Created by Tanner Bennett on 8/28/19.
+//  Copyright © 2019 Flipboard. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+/// \c FLEXTableViewSection itself doesn't know about the object being explored.
+/// Subclasses might need this info to provide useful information about the object. Instead
+/// of adding an abstract class to the class hierarchy, subclasses can conform to this protocol
+/// to indicate that the only info they need to be initialized is the object being explored.
+@protocol FLEXObjectInfoSection <NSObject>
+
++ (instancetype)forObject:(id)object;
+
+@end

+ 3 - 2
Classes/ObjectExplorers/Sections/Shortcuts/FLEXShortcutsSection.h

@@ -6,7 +6,8 @@
 //  Copyright © 2019 Flipboard. All rights reserved.
 //
 
-#import "FLEXExplorerSection.h"
+#import "FLEXTableViewSection.h"
+#import "FLEXObjectInfoSection.h"
 @class FLEXProperty, FLEXIvar, FLEXMethod;
 
 /// An abstract base class for custom object "shortcuts" where every
@@ -21,7 +22,7 @@
 /// If you create the section using \c forObject:rows:numberOfLines:
 /// then it will provide a view controller from \c viewControllerToPushForRow:
 /// automatically for rows that are a property/ivar/method.
-@interface FLEXShortcutsSection : FLEXExplorerSection <FLEXObjectInfoSection>
+@interface FLEXShortcutsSection : FLEXTableViewSection <FLEXObjectInfoSection>
 
 /// Uses \c kFLEXDefaultCell
 + (instancetype)forObject:(id)objectOrClass rowTitles:(NSArray<NSString *> *)titles;

+ 14 - 10
FLEX.xcodeproj/project.pbxproj

@@ -172,6 +172,8 @@
 		C362AE8223C7E9D1005A86AE /* NSMapTable+FLEX_Subscripting.m in Sources */ = {isa = PBXBuildFile; fileRef = C362AE8023C7E9D1005A86AE /* NSMapTable+FLEX_Subscripting.m */; };
 		C36B096523E0D4A1008F5D47 /* UIMenu+FLEX.h in Headers */ = {isa = PBXBuildFile; fileRef = C36B096323E0D4A1008F5D47 /* UIMenu+FLEX.h */; };
 		C36B096623E0D4A1008F5D47 /* UIMenu+FLEX.m in Sources */ = {isa = PBXBuildFile; fileRef = C36B096423E0D4A1008F5D47 /* UIMenu+FLEX.m */; };
+		C36B097023E1EDCD008F5D47 /* FLEXTableViewSection.h in Headers */ = {isa = PBXBuildFile; fileRef = C36B096E23E1EDCD008F5D47 /* FLEXTableViewSection.h */; };
+		C36B097123E1EDCD008F5D47 /* FLEXTableViewSection.m in Sources */ = {isa = PBXBuildFile; fileRef = C36B096F23E1EDCD008F5D47 /* FLEXTableViewSection.m */; };
 		C36FBFCB230F3B98008D95D5 /* FLEXMirror.m in Sources */ = {isa = PBXBuildFile; fileRef = C36FBFB9230F3B97008D95D5 /* FLEXMirror.m */; };
 		C36FBFCC230F3B98008D95D5 /* FLEXProtocolBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = C36FBFBA230F3B97008D95D5 /* FLEXProtocolBuilder.h */; };
 		C36FBFCD230F3B98008D95D5 /* FLEXMethod.m in Sources */ = {isa = PBXBuildFile; fileRef = C36FBFBB230F3B97008D95D5 /* FLEXMethod.m */; };
@@ -269,8 +271,7 @@
 		C3DC287C223ED5F200F48AA6 /* FLEXOSLogController.m in Sources */ = {isa = PBXBuildFile; fileRef = C34EE30721CB23CC00BD3A7C /* FLEXOSLogController.m */; };
 		C3E5D9FD2316E83700E655DB /* FLEXRuntime+Compare.h in Headers */ = {isa = PBXBuildFile; fileRef = C3E5D9FB2316E83700E655DB /* FLEXRuntime+Compare.h */; };
 		C3E5D9FE2316E83700E655DB /* FLEXRuntime+Compare.m in Sources */ = {isa = PBXBuildFile; fileRef = C3E5D9FC2316E83700E655DB /* FLEXRuntime+Compare.m */; };
-		C3E5DA02231700EE00E655DB /* FLEXExplorerSection.h in Headers */ = {isa = PBXBuildFile; fileRef = C3E5DA00231700EE00E655DB /* FLEXExplorerSection.h */; };
-		C3E5DA03231700EE00E655DB /* FLEXExplorerSection.m in Sources */ = {isa = PBXBuildFile; fileRef = C3E5DA01231700EE00E655DB /* FLEXExplorerSection.m */; };
+		C3E5DA02231700EE00E655DB /* FLEXObjectInfoSection.h in Headers */ = {isa = PBXBuildFile; fileRef = C3E5DA00231700EE00E655DB /* FLEXObjectInfoSection.h */; };
 		C3EE76BF22DFC63600EC0AA0 /* FLEXScopeCarousel.h in Headers */ = {isa = PBXBuildFile; fileRef = C3EE76BD22DFC63600EC0AA0 /* FLEXScopeCarousel.h */; };
 		C3EE76C022DFC63600EC0AA0 /* FLEXScopeCarousel.m in Sources */ = {isa = PBXBuildFile; fileRef = C3EE76BE22DFC63600EC0AA0 /* FLEXScopeCarousel.m */; };
 		C3F31D3D2267D883003C991A /* FLEXSubtitleTableViewCell.h in Headers */ = {isa = PBXBuildFile; fileRef = C3F31D342267D883003C991A /* FLEXSubtitleTableViewCell.h */; };
@@ -484,6 +485,8 @@
 		C362AE8023C7E9D1005A86AE /* NSMapTable+FLEX_Subscripting.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSMapTable+FLEX_Subscripting.m"; sourceTree = "<group>"; };
 		C36B096323E0D4A1008F5D47 /* UIMenu+FLEX.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIMenu+FLEX.h"; sourceTree = "<group>"; };
 		C36B096423E0D4A1008F5D47 /* UIMenu+FLEX.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIMenu+FLEX.m"; sourceTree = "<group>"; };
+		C36B096E23E1EDCD008F5D47 /* FLEXTableViewSection.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FLEXTableViewSection.h; sourceTree = "<group>"; };
+		C36B096F23E1EDCD008F5D47 /* FLEXTableViewSection.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLEXTableViewSection.m; sourceTree = "<group>"; };
 		C36FBFB9230F3B97008D95D5 /* FLEXMirror.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXMirror.m; sourceTree = "<group>"; };
 		C36FBFBA230F3B97008D95D5 /* FLEXProtocolBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXProtocolBuilder.h; sourceTree = "<group>"; };
 		C36FBFBB230F3B97008D95D5 /* FLEXMethod.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXMethod.m; sourceTree = "<group>"; };
@@ -576,8 +579,7 @@
 		C3DB9F632107FC9600B46809 /* FLEXObjectRef.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLEXObjectRef.m; sourceTree = "<group>"; };
 		C3E5D9FB2316E83700E655DB /* FLEXRuntime+Compare.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "FLEXRuntime+Compare.h"; sourceTree = "<group>"; };
 		C3E5D9FC2316E83700E655DB /* FLEXRuntime+Compare.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "FLEXRuntime+Compare.m"; sourceTree = "<group>"; };
-		C3E5DA00231700EE00E655DB /* FLEXExplorerSection.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FLEXExplorerSection.h; sourceTree = "<group>"; };
-		C3E5DA01231700EE00E655DB /* FLEXExplorerSection.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLEXExplorerSection.m; sourceTree = "<group>"; };
+		C3E5DA00231700EE00E655DB /* FLEXObjectInfoSection.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FLEXObjectInfoSection.h; sourceTree = "<group>"; };
 		C3EE76BD22DFC63600EC0AA0 /* FLEXScopeCarousel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FLEXScopeCarousel.h; sourceTree = "<group>"; };
 		C3EE76BE22DFC63600EC0AA0 /* FLEXScopeCarousel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLEXScopeCarousel.m; sourceTree = "<group>"; };
 		C3F31D342267D883003C991A /* FLEXSubtitleTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXSubtitleTableViewCell.h; sourceTree = "<group>"; };
@@ -1077,6 +1079,10 @@
 			children = (
 				C36B096823E1E26C008F5D47 /* Controllers */,
 				C3F31D3A2267D883003C991A /* Views */,
+				C36B096E23E1EDCD008F5D47 /* FLEXTableViewSection.h */,
+				C36B096F23E1EDCD008F5D47 /* FLEXTableViewSection.m */,
+				C3490E1D233BDD73002AE200 /* FLEXSingleRowSection.h */,
+				C3490E1E233BDD73002AE200 /* FLEXSingleRowSection.m */,
 			);
 			path = Core;
 			sourceTree = "<group>";
@@ -1184,10 +1190,7 @@
 		C3E5D9FF2317007F00E655DB /* Sections */ = {
 			isa = PBXGroup;
 			children = (
-				C3E5DA00231700EE00E655DB /* FLEXExplorerSection.h */,
-				C3E5DA01231700EE00E655DB /* FLEXExplorerSection.m */,
-				C3490E1D233BDD73002AE200 /* FLEXSingleRowSection.h */,
-				C3490E1E233BDD73002AE200 /* FLEXSingleRowSection.m */,
+				C3E5DA00231700EE00E655DB /* FLEXObjectInfoSection.h */,
 				C31C4A6723342A2200C35F12 /* FLEXMetadataSection.h */,
 				C31C4A6823342A2200C35F12 /* FLEXMetadataSection.m */,
 				C32A195C231732E800EB02AC /* FLEXCollectionContentSection.h */,
@@ -1241,7 +1244,7 @@
 				3A4C953E1B5B21410088C3F2 /* FLEXNetworkTransactionDetailTableViewController.h in Headers */,
 				3A4C95301B5B21410088C3F2 /* FLEXSystemLogMessage.h in Headers */,
 				C398625523AD6C67007E6793 /* FLEXObjcRuntimeViewController.h in Headers */,
-				C3E5DA02231700EE00E655DB /* FLEXExplorerSection.h in Headers */,
+				C3E5DA02231700EE00E655DB /* FLEXObjectInfoSection.h in Headers */,
 				C34D4EB023A2ABD900C1F903 /* FLEXLayerShortcuts.h in Headers */,
 				C3F646F623A04A7500D4A011 /* FLEXShortcut.h in Headers */,
 				C3878DBB23A749960038FDBE /* FLEXVariableEditorViewController.h in Headers */,
@@ -1275,6 +1278,7 @@
 				C3E5D9FD2316E83700E655DB /* FLEXRuntime+Compare.h in Headers */,
 				C3490E1F233BDD73002AE200 /* FLEXSingleRowSection.h in Headers */,
 				3A4C95281B5B21410088C3F2 /* FLEXInstancesTableViewController.h in Headers */,
+				C36B097023E1EDCD008F5D47 /* FLEXTableViewSection.h in Headers */,
 				3A4C950F1B5B21410088C3F2 /* FLEXMethodCallingViewController.h in Headers */,
 				3A4C94F51B5B21410088C3F2 /* FLEXArgumentInputObjectView.h in Headers */,
 				C3A9424923C78878006871A3 /* FLEXHierarchyViewController.h in Headers */,
@@ -1527,7 +1531,6 @@
 				C398625223AD6C67007E6793 /* TBKeyPathSearchController.m in Sources */,
 				C3E5D9FE2316E83700E655DB /* FLEXRuntime+Compare.m in Sources */,
 				71E1C2192307FBB800F5032A /* FLEXKeychainQuery.m in Sources */,
-				C3E5DA03231700EE00E655DB /* FLEXExplorerSection.m in Sources */,
 				C398627323AD7951007E6793 /* UIGestureRecognizer+Blocks.m in Sources */,
 				C3F646F723A04A7500D4A011 /* FLEXShortcut.m in Sources */,
 				3A4C94FE1B5B21410088C3F2 /* FLEXArgumentInputStructView.m in Sources */,
@@ -1574,6 +1577,7 @@
 				779B1ED31C0C4D7C001F5E49 /* FLEXTableColumnHeader.m in Sources */,
 				C37A0C94218BAC9600848CA7 /* FLEXObjcInternal.mm in Sources */,
 				C34D4EB523A2AF2A00C1F903 /* FLEXColorPreviewSection.m in Sources */,
+				C36B097123E1EDCD008F5D47 /* FLEXTableViewSection.m in Sources */,
 				3A4C94EA1B5B21410088C3F2 /* FLEXHierarchyTableViewController.m in Sources */,
 				3A4C95331B5B21410088C3F2 /* FLEXSystemLogTableViewCell.m in Sources */,
 				C3A9423523C3F98E006871A3 /* FHSViewController.m in Sources */,