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

Add "misc" metadata to the bottom of the object explorer

Add FLEXKeyValueTableViewCell for the "instance size" row, which has the title on the left and the value on the right
Tanner Bennett лет назад: 6
Родитель
Сommit
f24990d10f

+ 5 - 9
Classes/ObjectExplorers/FLEXObjectExplorer.h

@@ -6,11 +6,7 @@
 //  Copyright © 2019 Flipboard. All rights reserved.
 //  Copyright © 2019 Flipboard. All rights reserved.
 //
 //
 
 
-#import <Foundation/Foundation.h>
-#import "FLEXProperty.h"
-#import "FLEXIvar.h"
-#import "FLEXMethod.h"
-#import "FLEXProtocol.h"
+#import "FLEXRuntime+UIKitHelpers.h"
 
 
 @interface FLEXObjectExplorer : NSObject
 @interface FLEXObjectExplorer : NSObject
 
 
@@ -51,11 +47,11 @@
 @property (nonatomic, readonly) NSArray<FLEXProtocol *> *conformedProtocols;
 @property (nonatomic, readonly) NSArray<FLEXProtocol *> *conformedProtocols;
 @property (nonatomic, readonly) NSArray<Class> *classHierarchy;
 @property (nonatomic, readonly) NSArray<Class> *classHierarchy;
 
 
-@property (nonatomic, readonly) NSArray<NSNumber *> *allInstanceSizes;
-@property (nonatomic, readonly) NSUInteger instanceSize;
+@property (nonatomic, readonly) NSArray<FLEXStaticMetadata *> *allInstanceSizes;
+@property (nonatomic, readonly) FLEXStaticMetadata *instanceSize;
 
 
-@property (nonatomic, readonly) NSArray<NSString *> *allImageNames;
-@property (nonatomic, readonly) NSString *imageName;
+@property (nonatomic, readonly) NSArray<FLEXStaticMetadata *> *allImageNames;
+@property (nonatomic, readonly) FLEXStaticMetadata *imageName;
 
 
 - (void)reloadMetadata;
 - (void)reloadMetadata;
 - (void)reloadClassHierarchy;
 - (void)reloadClassHierarchy;

+ 13 - 6
Classes/ObjectExplorers/FLEXObjectExplorer.m

@@ -23,8 +23,8 @@
     NSMutableArray<NSArray<FLEXMethod *> *> *_allMethods;
     NSMutableArray<NSArray<FLEXMethod *> *> *_allMethods;
     NSMutableArray<NSArray<FLEXMethod *> *> *_allClassMethods;
     NSMutableArray<NSArray<FLEXMethod *> *> *_allClassMethods;
     NSMutableArray<NSArray<FLEXProtocol *> *> *_allConformedProtocols;
     NSMutableArray<NSArray<FLEXProtocol *> *> *_allConformedProtocols;
-    NSMutableArray<NSNumber *> *_allInstanceSizes;
-    NSMutableArray<NSString *> *_allImageNames;
+    NSMutableArray<FLEXStaticMetadata *> *_allInstanceSizes;
+    NSMutableArray<FLEXStaticMetadata *> *_allImageNames;
 }
 }
 @end
 @end
 
 
@@ -135,8 +135,14 @@
             superclass:superclass
             superclass:superclass
             kind:FLEXMetadataKindProtocols
             kind:FLEXMetadataKindProtocols
         ]];
         ]];
-        [_allInstanceSizes addObject:@(class_getInstanceSize(cls))];
-        [_allImageNames addObject:@(class_getImageName(cls))];
+        [_allInstanceSizes addObject:[FLEXStaticMetadata
+            style:FLEXStaticMetadataRowStyleKeyValue
+            title:@"Instance Size" number:@(class_getInstanceSize(cls))
+        ]];
+        [_allImageNames addObject:[FLEXStaticMetadata
+            style:FLEXStaticMetadataRowStyleDefault
+            title:@"Image Name" string:@(class_getImageName(cls))
+        ]];
     }
     }
 
 
     // Set up UIKit helper data
     // Set up UIKit helper data
@@ -163,7 +169,7 @@
     _methods = self.allMethods[self.classScope];
     _methods = self.allMethods[self.classScope];
     _classMethods = self.allClassMethods[self.classScope];
     _classMethods = self.allClassMethods[self.classScope];
     _conformedProtocols = self.allConformedProtocols[self.classScope];
     _conformedProtocols = self.allConformedProtocols[self.classScope];
-    _instanceSize = self.allInstanceSizes[self.classScope].unsignedIntegerValue;
+    _instanceSize = self.allInstanceSizes[self.classScope];
     _imageName = self.allImageNames[self.classScope];
     _imageName = self.allImageNames[self.classScope];
 }
 }
 
 
@@ -204,7 +210,8 @@
                     break;
                     break;
 
 
                 case FLEXMetadataKindProtocols:
                 case FLEXMetadataKindProtocols:
-                    return YES; // Protocols are already uniqued
+                case FLEXMetadataKindOther:
+                    return YES; // These types are already uniqued
                     break;
                     break;
                     
                     
                 // Ivars cannot be overidden
                 // Ivars cannot be overidden

+ 1 - 0
Classes/ObjectExplorers/FLEXObjectExplorerViewController.m

@@ -193,6 +193,7 @@
         [FLEXMetadataSection explorer:self.explorer kind:FLEXMetadataKindMethods],
         [FLEXMetadataSection explorer:self.explorer kind:FLEXMetadataKindMethods],
         [FLEXMetadataSection explorer:self.explorer kind:FLEXMetadataKindClassMethods],
         [FLEXMetadataSection explorer:self.explorer kind:FLEXMetadataKindClassMethods],
         [FLEXMetadataSection explorer:self.explorer kind:FLEXMetadataKindProtocols],
         [FLEXMetadataSection explorer:self.explorer kind:FLEXMetadataKindProtocols],
+        [FLEXMetadataSection explorer:self.explorer kind:FLEXMetadataKindOther],
 //        [FLEXMetadataSection explorer:self.explorer kind:FLEXMetadataKindClassHierarchy],
 //        [FLEXMetadataSection explorer:self.explorer kind:FLEXMetadataKindClassHierarchy],
         referencesSection
         referencesSection
     ]];
     ]];

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

@@ -16,6 +16,7 @@ typedef NS_ENUM(NSUInteger, FLEXMetadataKind) {
     FLEXMetadataKindMethods,
     FLEXMetadataKindMethods,
     FLEXMetadataKindClassMethods,
     FLEXMetadataKindClassMethods,
     FLEXMetadataKindProtocols,
     FLEXMetadataKindProtocols,
+    FLEXMetadataKindOther
 };
 };
 
 
 /// This section is used for displaying ObjC runtime metadata
 /// This section is used for displaying ObjC runtime metadata

+ 7 - 1
Classes/ObjectExplorers/Sections/FLEXMetadataSection.m

@@ -92,6 +92,8 @@
             return [self titleWithBaseName:@"Class Methods"];
             return [self titleWithBaseName:@"Class Methods"];
         case FLEXMetadataKindProtocols:
         case FLEXMetadataKindProtocols:
             return [self titleWithBaseName:@"Protocols"];
             return [self titleWithBaseName:@"Protocols"];
+        case FLEXMetadataKindOther:
+            return @"Miscellaneous";
     }
     }
 }
 }
 
 
@@ -130,6 +132,10 @@
             break;
             break;
         case FLEXMetadataKindProtocols:
         case FLEXMetadataKindProtocols:
             self.allMetadata = self.explorer.conformedProtocols;
             self.allMetadata = self.explorer.conformedProtocols;
+            break;
+        case FLEXMetadataKindOther:
+            self.allMetadata = @[self.explorer.instanceSize, self.explorer.imageName];
+            break;
     }
     }
 
 
     // Remove excluded metadata
     // Remove excluded metadata
@@ -155,7 +161,7 @@
 }
 }
 
 
 - (NSString *)reuseIdentifierForRow:(NSInteger)row {
 - (NSString *)reuseIdentifierForRow:(NSInteger)row {
-    return kFLEXCodeFontCell;
+    return [self.metadata[row] reuseIdentifierWithTarget:self.explorer.object] ?: kFLEXCodeFontCell;
 }
 }
 
 
 - (UIViewController *)viewControllerToPushForRow:(NSInteger)row {
 - (UIViewController *)viewControllerToPushForRow:(NSInteger)row {

+ 13 - 0
Classes/ObjectExplorers/Views/FLEXKeyValueTableViewCell.h

@@ -0,0 +1,13 @@
+//
+//  FLEXKeyValueTableViewCell.h
+//  FLEX
+//
+//  Created by Tanner Bennett on 1/23/20.
+//  Copyright © 2020 Flipboard. All rights reserved.
+//
+
+#import "FLEXTableViewCell.h"
+
+@interface FLEXKeyValueTableViewCell : FLEXTableViewCell
+
+@end

+ 17 - 0
Classes/ObjectExplorers/Views/FLEXKeyValueTableViewCell.m

@@ -0,0 +1,17 @@
+//
+//  FLEXKeyValueTableViewCell.m
+//  FLEX
+//
+//  Created by Tanner Bennett on 1/23/20.
+//  Copyright © 2020 Flipboard. All rights reserved.
+//
+
+#import "FLEXKeyValueTableViewCell.h"
+
+@implementation FLEXKeyValueTableViewCell
+
+- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
+    return [super initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:reuseIdentifier];
+}
+
+@end

+ 1 - 2
Classes/ObjectExplorers/Views/FLEXSubtitleTableViewCell.m

@@ -10,8 +10,7 @@
 
 
 @implementation FLEXSubtitleTableViewCell
 @implementation FLEXSubtitleTableViewCell
 
 
-- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
-{
+- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
     return [super initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:reuseIdentifier];
     return [super initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:reuseIdentifier];
 }
 }
 
 

+ 3 - 1
Classes/ObjectExplorers/Views/FLEXTableView.h

@@ -12,7 +12,7 @@
 
 
 typedef NSString * FLEXTableViewCellReuseIdentifier;
 typedef NSString * FLEXTableViewCellReuseIdentifier;
 
 
-/// A regular \c UITableViewCell initialized with \c UITableViewCellStyleDefault
+/// A regular \c FLEXTableViewCell initialized with \c UITableViewCellStyleDefault
 extern FLEXTableViewCellReuseIdentifier const kFLEXDefaultCell;
 extern FLEXTableViewCellReuseIdentifier const kFLEXDefaultCell;
 /// A \c FLEXSubtitleTableViewCell initialized with \c UITableViewCellStyleSubtitle
 /// A \c FLEXSubtitleTableViewCell initialized with \c UITableViewCellStyleSubtitle
 extern FLEXTableViewCellReuseIdentifier const kFLEXDetailCell;
 extern FLEXTableViewCellReuseIdentifier const kFLEXDetailCell;
@@ -20,6 +20,8 @@ extern FLEXTableViewCellReuseIdentifier const kFLEXDetailCell;
 extern FLEXTableViewCellReuseIdentifier const kFLEXMultilineCell;
 extern FLEXTableViewCellReuseIdentifier const kFLEXMultilineCell;
 /// A \c FLEXMultilineTableViewCell initialized with \c UITableViewCellStyleSubtitle
 /// A \c FLEXMultilineTableViewCell initialized with \c UITableViewCellStyleSubtitle
 extern FLEXTableViewCellReuseIdentifier const kFLEXMultilineDetailCell;
 extern FLEXTableViewCellReuseIdentifier const kFLEXMultilineDetailCell;
+/// A \c FLEXTableViewCell initialized with \c UITableViewCellStyleValue1
+extern FLEXTableViewCellReuseIdentifier const kFLEXKeyValueCell;
 /// A \c FLEXSubtitleTableViewCell which uses monospaced fonts for both labels
 /// A \c FLEXSubtitleTableViewCell which uses monospaced fonts for both labels
 extern FLEXTableViewCellReuseIdentifier const kFLEXCodeFontCell;
 extern FLEXTableViewCellReuseIdentifier const kFLEXCodeFontCell;
 
 

+ 3 - 0
Classes/ObjectExplorers/Views/FLEXTableView.m

@@ -10,12 +10,14 @@
 #import "FLEXUtility.h"
 #import "FLEXUtility.h"
 #import "FLEXSubtitleTableViewCell.h"
 #import "FLEXSubtitleTableViewCell.h"
 #import "FLEXMultilineTableViewCell.h"
 #import "FLEXMultilineTableViewCell.h"
+#import "FLEXKeyValueTableViewCell.h"
 #import "FLEXCodeFontCell.h"
 #import "FLEXCodeFontCell.h"
 
 
 FLEXTableViewCellReuseIdentifier const kFLEXDefaultCell = @"kFLEXDefaultCell";
 FLEXTableViewCellReuseIdentifier const kFLEXDefaultCell = @"kFLEXDefaultCell";
 FLEXTableViewCellReuseIdentifier const kFLEXDetailCell = @"kFLEXDetailCell";
 FLEXTableViewCellReuseIdentifier const kFLEXDetailCell = @"kFLEXDetailCell";
 FLEXTableViewCellReuseIdentifier const kFLEXMultilineCell = @"kFLEXMultilineCell";
 FLEXTableViewCellReuseIdentifier const kFLEXMultilineCell = @"kFLEXMultilineCell";
 FLEXTableViewCellReuseIdentifier const kFLEXMultilineDetailCell = @"kFLEXMultilineDetailCell";
 FLEXTableViewCellReuseIdentifier const kFLEXMultilineDetailCell = @"kFLEXMultilineDetailCell";
+FLEXTableViewCellReuseIdentifier const kFLEXKeyValueCell = @"kFLEXKeyValueCell";
 FLEXTableViewCellReuseIdentifier const kFLEXCodeFontCell = @"kFLEXCodeFontCell";
 FLEXTableViewCellReuseIdentifier const kFLEXCodeFontCell = @"kFLEXCodeFontCell";
 
 
 #pragma mark Private
 #pragma mark Private
@@ -93,6 +95,7 @@ FLEXTableViewCellReuseIdentifier const kFLEXCodeFontCell = @"kFLEXCodeFontCell";
             kFLEXDetailCell : [FLEXSubtitleTableViewCell class],
             kFLEXDetailCell : [FLEXSubtitleTableViewCell class],
             kFLEXMultilineCell : [FLEXMultilineTableViewCell class],
             kFLEXMultilineCell : [FLEXMultilineTableViewCell class],
             kFLEXMultilineDetailCell : [FLEXMultilineDetailTableViewCell class],
             kFLEXMultilineDetailCell : [FLEXMultilineDetailTableViewCell class],
+            kFLEXKeyValueCell : [FLEXKeyValueTableViewCell class],
             kFLEXCodeFontCell : [FLEXCodeFontCell class],
             kFLEXCodeFontCell : [FLEXCodeFontCell class],
         }];
         }];
     }
     }

+ 20 - 1
Classes/Utility/Categories/FLEXRuntime+UIKitHelpers.h

@@ -13,7 +13,9 @@
 #import "FLEXProtocol.h"
 #import "FLEXProtocol.h"
 
 
 @protocol FLEXRuntimeMetadata <NSObject>
 @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;
 @property (nonatomic, readonly) NSString *name;
 /// 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;
@@ -33,6 +35,8 @@
 - (UIViewController *)editorWithTarget:(id)object;
 - (UIViewController *)editorWithTarget:(id)object;
 /// Used to determine present which interactions are possible to the user
 /// Used to determine present which interactions are possible to the user
 - (UITableViewCellAccessoryType)suggestedAccessoryTypeWithTarget:(id)object;
 - (UITableViewCellAccessoryType)suggestedAccessoryTypeWithTarget:(id)object;
+/// Return nil to use the default reuse identifier
+- (NSString *)reuseIdentifierWithTarget:(id)object;
 
 
 @end
 @end
 
 
@@ -44,3 +48,18 @@
 @interface FLEXMethodBase (UIKitHelpers) <FLEXRuntimeMetadata> @end
 @interface FLEXMethodBase (UIKitHelpers) <FLEXRuntimeMetadata> @end
 @interface FLEXMethod (UIKitHelpers) <FLEXRuntimeMetadata> @end
 @interface FLEXMethod (UIKitHelpers) <FLEXRuntimeMetadata> @end
 @interface FLEXProtocol (UIKitHelpers) <FLEXRuntimeMetadata> @end
 @interface FLEXProtocol (UIKitHelpers) <FLEXRuntimeMetadata> @end
+
+typedef NS_ENUM(NSUInteger, FLEXStaticMetadataRowStyle)
+{
+    FLEXStaticMetadataRowStyleSubtitle,
+    FLEXStaticMetadataRowStyleKeyValue,
+    FLEXStaticMetadataRowStyleDefault = FLEXStaticMetadataRowStyleSubtitle,
+};
+
+/// Displays a small row as a static key-value pair of information.
+@interface FLEXStaticMetadata : NSObject <FLEXRuntimeMetadata>
+
++ (instancetype)style:(FLEXStaticMetadataRowStyle)style title:(NSString *)title string:(NSString *)string;
++ (instancetype)style:(FLEXStaticMetadataRowStyle)style title:(NSString *)title number:(NSNumber *)number;
+
+@end

+ 82 - 0
Classes/Utility/Categories/FLEXRuntime+UIKitHelpers.m

@@ -13,6 +13,7 @@
 #import "FLEXObjectExplorerFactory.h"
 #import "FLEXObjectExplorerFactory.h"
 #import "FLEXFieldEditorViewController.h"
 #import "FLEXFieldEditorViewController.h"
 #import "FLEXMethodCallingViewController.h"
 #import "FLEXMethodCallingViewController.h"
+#import "FLEXTableView.h"
 
 
 @implementation FLEXProperty (UIKitHelpers)
 @implementation FLEXProperty (UIKitHelpers)
 
 
@@ -101,6 +102,8 @@
     }
     }
 }
 }
 
 
+- (NSString *)reuseIdentifierWithTarget:(id)object { return nil; }
+
 @end
 @end
 
 
 
 
@@ -168,6 +171,8 @@
     }
     }
 }
 }
 
 
+- (NSString *)reuseIdentifierWithTarget:(id)object { return nil; }
+
 @end
 @end
 
 
 
 
@@ -208,6 +213,8 @@
     return UITableViewCellAccessoryNone;
     return UITableViewCellAccessoryNone;
 }
 }
 
 
+- (NSString *)reuseIdentifierWithTarget:(id)object { return nil; }
+
 @end
 @end
 
 
 @implementation FLEXMethod (UIKitHelpers)
 @implementation FLEXMethod (UIKitHelpers)
@@ -268,4 +275,79 @@
     return UITableViewCellAccessoryDisclosureIndicator;
     return UITableViewCellAccessoryDisclosureIndicator;
 }
 }
 
 
+- (NSString *)reuseIdentifierWithTarget:(id)object { return nil; }
+
+@end
+
+
+@interface FLEXStaticMetadata ()
+@property (nonatomic, readonly) FLEXTableViewCellReuseIdentifier reuse;
+@property (nonatomic, readonly) NSString *subtitle;
+@property (nonatomic, readonly) id metadata;
+@end
+
+@implementation FLEXStaticMetadata
+@synthesize name = _name;
+@synthesize tag = _tag;
+
++ (instancetype)style:(FLEXStaticMetadataRowStyle)style title:(NSString *)title string:(NSString *)string {
+    return [[self alloc] initWithStyle:style title:title subtitle:string];
+}
+
++ (instancetype)style:(FLEXStaticMetadataRowStyle)style title:(NSString *)title number:(NSNumber *)number {
+    return [[self alloc] initWithStyle:style title:title subtitle:number.stringValue];
+}
+
+- (id)initWithStyle:(FLEXStaticMetadataRowStyle)style title:(NSString *)title subtitle:(NSString *)subtitle  {
+    self = [super init];
+    if (self) {
+        if (style == FLEXStaticMetadataRowStyleKeyValue) {
+            _reuse = kFLEXKeyValueCell;
+        } else {
+            _reuse = kFLEXMultilineDetailCell;
+        }
+
+        _name = title;
+        _subtitle = subtitle;
+    }
+
+    return self;
+}
+
+- (NSString *)description {
+    return self.name;
+}
+
+- (NSString *)reuseIdentifierWithTarget:(id)object {
+    return self.reuse;
+}
+
+- (BOOL)isEditable {
+    return NO;
+}
+
+- (BOOL)isCallable {
+    return NO;
+}
+
+- (id)currentValueWithTarget:(id)object {
+    return nil;
+}
+
+- (NSString *)previewWithTarget:(id)object {
+    return self.subtitle;
+}
+
+- (UIViewController *)viewerWithTarget:(id)object {
+    return nil;
+}
+
+- (UIViewController *)editorWithTarget:(id)object {
+    return nil;
+}
+
+- (UITableViewCellAccessoryType)suggestedAccessoryTypeWithTarget:(id)object {
+    return UITableViewCellAccessoryNone;
+}
+
 @end
 @end

+ 8 - 0
FLEX.xcodeproj/project.pbxproj

@@ -153,6 +153,8 @@
 		C33C825F2316DC8600DD2451 /* FLEXObjectExplorer.m in Sources */ = {isa = PBXBuildFile; fileRef = C33C825D2316DC8600DD2451 /* FLEXObjectExplorer.m */; };
 		C33C825F2316DC8600DD2451 /* FLEXObjectExplorer.m in Sources */ = {isa = PBXBuildFile; fileRef = C33C825D2316DC8600DD2451 /* FLEXObjectExplorer.m */; };
 		C33E46AF223B02CD004BD0E6 /* FLEXASLLogController.h in Headers */ = {isa = PBXBuildFile; fileRef = C33E46AD223B02CD004BD0E6 /* FLEXASLLogController.h */; };
 		C33E46AF223B02CD004BD0E6 /* FLEXASLLogController.h in Headers */ = {isa = PBXBuildFile; fileRef = C33E46AD223B02CD004BD0E6 /* FLEXASLLogController.h */; };
 		C33E46B0223B02CD004BD0E6 /* FLEXASLLogController.m in Sources */ = {isa = PBXBuildFile; fileRef = C33E46AE223B02CD004BD0E6 /* FLEXASLLogController.m */; };
 		C33E46B0223B02CD004BD0E6 /* FLEXASLLogController.m in Sources */ = {isa = PBXBuildFile; fileRef = C33E46AE223B02CD004BD0E6 /* FLEXASLLogController.m */; };
+		C3474C4023DA496400466532 /* FLEXKeyValueTableViewCell.h in Headers */ = {isa = PBXBuildFile; fileRef = C3474C3E23DA496400466532 /* FLEXKeyValueTableViewCell.h */; };
+		C3474C4123DA496400466532 /* FLEXKeyValueTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = C3474C3F23DA496400466532 /* FLEXKeyValueTableViewCell.m */; };
 		C3490E1F233BDD73002AE200 /* FLEXSingleRowSection.h in Headers */ = {isa = PBXBuildFile; fileRef = C3490E1D233BDD73002AE200 /* FLEXSingleRowSection.h */; };
 		C3490E1F233BDD73002AE200 /* FLEXSingleRowSection.h in Headers */ = {isa = PBXBuildFile; fileRef = C3490E1D233BDD73002AE200 /* FLEXSingleRowSection.h */; };
 		C3490E20233BDD73002AE200 /* FLEXSingleRowSection.m in Sources */ = {isa = PBXBuildFile; fileRef = C3490E1E233BDD73002AE200 /* FLEXSingleRowSection.m */; };
 		C3490E20233BDD73002AE200 /* FLEXSingleRowSection.m in Sources */ = {isa = PBXBuildFile; fileRef = C3490E1E233BDD73002AE200 /* FLEXSingleRowSection.m */; };
 		C34C9BDD23A7F2740031CA3E /* FLEXRuntime+UIKitHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = C34C9BDB23A7F2740031CA3E /* FLEXRuntime+UIKitHelpers.h */; };
 		C34C9BDD23A7F2740031CA3E /* FLEXRuntime+UIKitHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = C34C9BDB23A7F2740031CA3E /* FLEXRuntime+UIKitHelpers.h */; };
@@ -459,6 +461,8 @@
 		C33C825D2316DC8600DD2451 /* FLEXObjectExplorer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = FLEXObjectExplorer.m; path = Classes/ObjectExplorers/FLEXObjectExplorer.m; sourceTree = SOURCE_ROOT; };
 		C33C825D2316DC8600DD2451 /* FLEXObjectExplorer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = FLEXObjectExplorer.m; path = Classes/ObjectExplorers/FLEXObjectExplorer.m; sourceTree = SOURCE_ROOT; };
 		C33E46AD223B02CD004BD0E6 /* FLEXASLLogController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FLEXASLLogController.h; sourceTree = "<group>"; };
 		C33E46AD223B02CD004BD0E6 /* FLEXASLLogController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FLEXASLLogController.h; sourceTree = "<group>"; };
 		C33E46AE223B02CD004BD0E6 /* FLEXASLLogController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLEXASLLogController.m; sourceTree = "<group>"; };
 		C33E46AE223B02CD004BD0E6 /* FLEXASLLogController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLEXASLLogController.m; sourceTree = "<group>"; };
+		C3474C3E23DA496400466532 /* FLEXKeyValueTableViewCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FLEXKeyValueTableViewCell.h; sourceTree = "<group>"; };
+		C3474C3F23DA496400466532 /* FLEXKeyValueTableViewCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLEXKeyValueTableViewCell.m; sourceTree = "<group>"; };
 		C3490E1D233BDD73002AE200 /* FLEXSingleRowSection.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FLEXSingleRowSection.h; sourceTree = "<group>"; };
 		C3490E1D233BDD73002AE200 /* FLEXSingleRowSection.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FLEXSingleRowSection.h; sourceTree = "<group>"; };
 		C3490E1E233BDD73002AE200 /* FLEXSingleRowSection.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLEXSingleRowSection.m; sourceTree = "<group>"; };
 		C3490E1E233BDD73002AE200 /* FLEXSingleRowSection.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLEXSingleRowSection.m; sourceTree = "<group>"; };
 		C34C9BDB23A7F2740031CA3E /* FLEXRuntime+UIKitHelpers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "FLEXRuntime+UIKitHelpers.h"; sourceTree = "<group>"; };
 		C34C9BDB23A7F2740031CA3E /* FLEXRuntime+UIKitHelpers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "FLEXRuntime+UIKitHelpers.h"; sourceTree = "<group>"; };
@@ -1170,6 +1174,8 @@
 				C3F31D372267D883003C991A /* FLEXSubtitleTableViewCell.m */,
 				C3F31D372267D883003C991A /* FLEXSubtitleTableViewCell.m */,
 				C3F31D362267D883003C991A /* FLEXMultilineTableViewCell.h */,
 				C3F31D362267D883003C991A /* FLEXMultilineTableViewCell.h */,
 				C3F31D382267D883003C991A /* FLEXMultilineTableViewCell.m */,
 				C3F31D382267D883003C991A /* FLEXMultilineTableViewCell.m */,
+				C3474C3E23DA496400466532 /* FLEXKeyValueTableViewCell.h */,
+				C3474C3F23DA496400466532 /* FLEXKeyValueTableViewCell.m */,
 				C383C3C323B6BB81007A321B /* FLEXCodeFontCell.h */,
 				C383C3C323B6BB81007A321B /* FLEXCodeFontCell.h */,
 				C383C3C423B6BB81007A321B /* FLEXCodeFontCell.m */,
 				C383C3C423B6BB81007A321B /* FLEXCodeFontCell.m */,
 			);
 			);
@@ -1245,6 +1251,7 @@
 				3A4C94F11B5B21410088C3F2 /* FLEXArgumentInputFontsPickerView.h in Headers */,
 				3A4C94F11B5B21410088C3F2 /* FLEXArgumentInputFontsPickerView.h in Headers */,
 				C3BFD070233C23ED0015FB82 /* NSArray+Functional.h in Headers */,
 				C3BFD070233C23ED0015FB82 /* NSArray+Functional.h in Headers */,
 				C398682923AC370100E9E391 /* FLEXViewShortcuts.h in Headers */,
 				C398682923AC370100E9E391 /* FLEXViewShortcuts.h in Headers */,
+				C3474C4023DA496400466532 /* FLEXKeyValueTableViewCell.h in Headers */,
 				779B1ED61C0C4D7C001F5E49 /* FLEXTableContentViewController.h in Headers */,
 				779B1ED61C0C4D7C001F5E49 /* FLEXTableContentViewController.h in Headers */,
 				3A4C95221B5B21410088C3F2 /* FLEXFileBrowserSearchOperation.h in Headers */,
 				3A4C95221B5B21410088C3F2 /* FLEXFileBrowserSearchOperation.h in Headers */,
 				C33E46AF223B02CD004BD0E6 /* FLEXASLLogController.h in Headers */,
 				C33E46AF223B02CD004BD0E6 /* FLEXASLLogController.h in Headers */,
@@ -1546,6 +1553,7 @@
 				C33C825F2316DC8600DD2451 /* FLEXObjectExplorer.m in Sources */,
 				C33C825F2316DC8600DD2451 /* FLEXObjectExplorer.m in Sources */,
 				C383C3C123B6B429007A321B /* NSTimer+Blocks.m in Sources */,
 				C383C3C123B6B429007A321B /* NSTimer+Blocks.m in Sources */,
 				3A4C94FA1B5B21410088C3F2 /* FLEXArgumentInputNumberView.m in Sources */,
 				3A4C94FA1B5B21410088C3F2 /* FLEXArgumentInputNumberView.m in Sources */,
+				C3474C4123DA496400466532 /* FLEXKeyValueTableViewCell.m in Sources */,
 				779B1ED71C0C4D7C001F5E49 /* FLEXTableContentViewController.m in Sources */,
 				779B1ED71C0C4D7C001F5E49 /* FLEXTableContentViewController.m in Sources */,
 				C36FBFCB230F3B98008D95D5 /* FLEXMirror.m in Sources */,
 				C36FBFCB230F3B98008D95D5 /* FLEXMirror.m in Sources */,
 				C36FBFD5230F3B98008D95D5 /* FLEXMethodBase.m in Sources */,
 				C36FBFD5230F3B98008D95D5 /* FLEXMethodBase.m in Sources */,