Skip to content

Commit ba36647

Browse files
committed
Enable displaying ivar names for custom struct types
FLEXMetadataExtras.h
1 parent 9d97533 commit ba36647

12 files changed

+148
-35
lines changed

Classes/Editing/ArgumentInputViews/FLEXArgumentInputStructView.h

+3
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,7 @@
1010

1111
@interface FLEXArgumentInputStructView : FLEXArgumentInputView
1212

13+
/// Enable displaying ivar names for custom struct types
14+
+ (void)registerFieldNames:(NSArray<NSString *> *)names forTypeEncoding:(NSString *)typeEncoding;
15+
1316
@end

Classes/Editing/ArgumentInputViews/FLEXArgumentInputStructView.m

+41-33
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,41 @@ @interface FLEXArgumentInputStructView ()
1919

2020
@implementation FLEXArgumentInputStructView
2121

22+
static NSMutableDictionary<NSString *, NSArray<NSString *> *> *structFieldNameRegistrar = nil;
23+
+ (void)initialize {
24+
if (self == [FLEXArgumentInputStructView class]) {
25+
structFieldNameRegistrar = [NSMutableDictionary new];
26+
[self registerDefaultFieldNames];
27+
}
28+
}
29+
30+
+ (void)registerDefaultFieldNames {
31+
NSDictionary *defaults = @{
32+
@(@encode(CGRect)): @[@"CGPoint origin", @"CGSize size"],
33+
@(@encode(CGPoint)): @[@"CGFloat x", @"CGFloat y"],
34+
@(@encode(CGSize)): @[@"CGFloat width", @"CGFloat height"],
35+
@(@encode(CGVector)): @[@"CGFloat dx", @"CGFloat dy"],
36+
@(@encode(UIEdgeInsets)): @[@"CGFloat top", @"CGFloat left", @"CGFloat bottom", @"CGFloat right"],
37+
@(@encode(UIOffset)): @[@"CGFloat horizontal", @"CGFloat vertical"],
38+
@(@encode(NSRange)): @[@"NSUInteger location", @"NSUInteger length"],
39+
@(@encode(CATransform3D)): @[@"CGFloat m11", @"CGFloat m12", @"CGFloat m13", @"CGFloat m14",
40+
@"CGFloat m21", @"CGFloat m22", @"CGFloat m23", @"CGFloat m24",
41+
@"CGFloat m31", @"CGFloat m32", @"CGFloat m33", @"CGFloat m34",
42+
@"CGFloat m41", @"CGFloat m42", @"CGFloat m43", @"CGFloat m44"],
43+
@(@encode(CGAffineTransform)): @[@"CGFloat a", @"CGFloat b",
44+
@"CGFloat c", @"CGFloat d",
45+
@"CGFloat tx", @"CGFloat ty"],
46+
};
47+
48+
[structFieldNameRegistrar addEntriesFromDictionary:defaults];
49+
50+
if (@available(iOS 11.0, *)) {
51+
structFieldNameRegistrar[@(@encode(NSDirectionalEdgeInsets))] = @[
52+
@"CGFloat top", @"CGFloat leading", @"CGFloat bottom", @"CGFloat trailing"
53+
];
54+
}
55+
}
56+
2257
- (instancetype)initWithArgumentTypeEncoding:(const char *)typeEncoding {
2358
self = [super initWithArgumentTypeEncoding:typeEncoding];
2459
if (self) {
@@ -181,40 +216,13 @@ + (BOOL)supportsObjCType:(const char *)type withCurrentValue:(id)value {
181216
return NO;
182217
}
183218

219+
+ (void)registerFieldNames:(NSArray<NSString *> *)names forTypeEncoding:(NSString *)typeEncoding {
220+
NSParameterAssert(typeEncoding); NSParameterAssert(names);
221+
structFieldNameRegistrar[typeEncoding] = names;
222+
}
223+
184224
+ (NSArray<NSString *> *)customFieldTitlesForTypeEncoding:(const char *)typeEncoding {
185-
NSArray<NSString *> *customTitles = nil;
186-
if (strcmp(typeEncoding, @encode(CGRect)) == 0) {
187-
customTitles = @[@"CGPoint origin", @"CGSize size"];
188-
} else if (strcmp(typeEncoding, @encode(CGPoint)) == 0) {
189-
customTitles = @[@"CGFloat x", @"CGFloat y"];
190-
} else if (strcmp(typeEncoding, @encode(CGSize)) == 0) {
191-
customTitles = @[@"CGFloat width", @"CGFloat height"];
192-
} else if (strcmp(typeEncoding, @encode(CGVector)) == 0) {
193-
customTitles = @[@"CGFloat dx", @"CGFloat dy"];
194-
} else if (strcmp(typeEncoding, @encode(UIEdgeInsets)) == 0) {
195-
customTitles = @[@"CGFloat top", @"CGFloat left", @"CGFloat bottom", @"CGFloat right"];
196-
} else if (strcmp(typeEncoding, @encode(UIOffset)) == 0) {
197-
customTitles = @[@"CGFloat horizontal", @"CGFloat vertical"];
198-
} else if (strcmp(typeEncoding, @encode(NSRange)) == 0) {
199-
customTitles = @[@"NSUInteger location", @"NSUInteger length"];
200-
} else if (strcmp(typeEncoding, @encode(CATransform3D)) == 0) {
201-
customTitles = @[@"CGFloat m11", @"CGFloat m12", @"CGFloat m13", @"CGFloat m14",
202-
@"CGFloat m21", @"CGFloat m22", @"CGFloat m23", @"CGFloat m24",
203-
@"CGFloat m31", @"CGFloat m32", @"CGFloat m33", @"CGFloat m34",
204-
@"CGFloat m41", @"CGFloat m42", @"CGFloat m43", @"CGFloat m44"];
205-
} else if (strcmp(typeEncoding, @encode(CGAffineTransform)) == 0) {
206-
customTitles = @[@"CGFloat a", @"CGFloat b",
207-
@"CGFloat c", @"CGFloat d",
208-
@"CGFloat tx", @"CGFloat ty"];
209-
} else {
210-
if (@available(iOS 11.0, *)) {
211-
if (strcmp(typeEncoding, @encode(NSDirectionalEdgeInsets)) == 0) {
212-
customTitles = @[@"CGFloat top", @"CGFloat leading",
213-
@"CGFloat bottom", @"CGFloat trailing"];
214-
}
215-
}
216-
}
217-
return customTitles;
225+
return structFieldNameRegistrar[@(typeEncoding)];
218226
}
219227

220228
@end

Classes/Editing/FLEXArgumentInputViewFactory.h

+3
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,7 @@
2121
/// Useful when deciding whether to edit or explore a property, ivar, or NSUserDefaults value.
2222
+ (BOOL)canEditFieldWithTypeEncoding:(const char *)typeEncoding currentValue:(id)currentValue;
2323

24+
/// Enable displaying ivar names for custom struct types
25+
+ (void)registerFieldNames:(NSArray<NSString *> *)names forTypeEncoding:(NSString *)typeEncoding;
26+
2427
@end

Classes/Editing/FLEXArgumentInputViewFactory.m

+5
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,9 @@ + (BOOL)canEditFieldWithTypeEncoding:(const char *)typeEncoding currentValue:(id
6767
return [self argumentInputViewSubclassForTypeEncoding:typeEncoding currentValue:currentValue] != nil;
6868
}
6969

70+
/// Enable displaying ivar names for custom struct types
71+
+ (void)registerFieldNames:(NSArray<NSString *> *)names forTypeEncoding:(NSString *)typeEncoding {
72+
[FLEXArgumentInputStructView registerFieldNames:names forTypeEncoding:typeEncoding];
73+
}
74+
7075
@end

Classes/Editing/FLEXFieldEditorViewController.m

+21-2
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@
1111
#import "FLEXArgumentInputViewFactory.h"
1212
#import "FLEXPropertyAttributes.h"
1313
#import "FLEXRuntimeUtility.h"
14+
#import "FLEXMetadataExtras.h"
1415
#import "FLEXUtility.h"
1516
#import "FLEXColor.h"
1617
#import "UIBarButtonItem+FLEX.h"
1718

1819
@interface FLEXFieldEditorViewController () <FLEXArgumentInputViewDelegate>
1920

21+
@property (nonatomic, readonly) id<FLEXMetadataAuxiliaryInfo> auxiliaryInfoProvider;
2022
@property (nonatomic) FLEXProperty *property;
2123
@property (nonatomic) FLEXIvar *ivar;
2224

@@ -30,14 +32,14 @@ @implementation FLEXFieldEditorViewController
3032

3133
#pragma mark - Initialization
3234

33-
+ (instancetype)target:(id)target property:(nonnull FLEXProperty *)property commitHandler:(void(^_Nullable)(void))onCommit {
35+
+ (instancetype)target:(id)target property:(nonnull FLEXProperty *)property commitHandler:(void(^)(void))onCommit {
3436
FLEXFieldEditorViewController *editor = [self target:target data:property commitHandler:onCommit];
3537
editor.title = [@"Property: " stringByAppendingString:property.name];
3638
editor.property = property;
3739
return editor;
3840
}
3941

40-
+ (instancetype)target:(id)target ivar:(nonnull FLEXIvar *)ivar commitHandler:(void(^_Nullable)(void))onCommit {
42+
+ (instancetype)target:(id)target ivar:(nonnull FLEXIvar *)ivar commitHandler:(void(^)(void))onCommit {
4143
FLEXFieldEditorViewController *editor = [self target:target data:ivar commitHandler:onCommit];
4244
editor.title = [@"Ivar: " stringByAppendingString:ivar.name];
4345
editor.ivar = ivar;
@@ -61,6 +63,8 @@ - (void)viewDidLoad {
6163
self.toolbarItems = @[
6264
UIBarButtonItem.flex_flexibleSpace, self.getterButton, self.actionButton
6365
];
66+
67+
[self registerAuxiliaryInfo];
6468

6569
// Configure input view
6670
self.fieldEditorView.fieldDescription = self.fieldDescription;
@@ -122,6 +126,17 @@ - (void)argumentInputViewValueDidChange:(FLEXArgumentInputView *)argumentInputVi
122126

123127
#pragma mark - Private
124128

129+
- (void)registerAuxiliaryInfo {
130+
// This is how Reflex will get Swift struct field names into the editor at runtime
131+
NSDictionary<NSString *, NSArray *> *labels = [self.auxiliaryInfoProvider
132+
auxiliaryInfoForKey:FLEXAuxiliarynfoKeyFieldLabels
133+
];
134+
135+
for (NSString *type in labels) {
136+
[FLEXArgumentInputViewFactory registerFieldNames:labels[type] forTypeEncoding:type];
137+
}
138+
}
139+
125140
- (id)currentValue {
126141
if (self.property) {
127142
return [self.property getValue:self.target];
@@ -130,6 +145,10 @@ - (id)currentValue {
130145
}
131146
}
132147

148+
- (id<FLEXMetadataAuxiliaryInfo>)auxiliaryInfoProvider {
149+
return self.ivar ?: self.property;
150+
}
151+
133152
- (const FLEXTypeEncoding *)typeEncoding {
134153
if (self.property) {
135154
return self.property.attributes.typeEncoding.UTF8String;

Classes/FLEX-Runtime.h

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#import "FLEXPropertyAttributes.h"
2222
#import "FLEXRuntime+Compare.h"
2323
#import "FLEXRuntime+UIKitHelpers.h"
24+
#import "FLEXMetadataExtras.h"
2425

2526
#import "FLEXProtocolBuilder.h"
2627
#import "FLEXClassBuilder.h"

Classes/Headers/FLEXMetadataExtras.h

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../Classes/Utility/Runtime/Objc/Reflection/FLEXMetadataExtras.h

Classes/Manager/FLEXManager+Extensibility.h

+5
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ NS_ASSUME_NONNULL_BEGIN
5252
/// Removes all registered global entries.
5353
- (void)clearGlobalEntries;
5454

55+
#pragma mark - Editing
56+
57+
/// Enable displaying ivar names for custom struct types
58+
+ (void)registerFieldNames:(NSArray<NSString *> *)names forTypeEncoding:(NSString *)typeEncoding;
59+
5560
#pragma mark - Simulator Shortcuts
5661

5762
/// Simulator keyboard shortcuts are enabled by default.

Classes/Manager/FLEXManager+Extensibility.m

+8
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#import "FLEXNetworkMITMViewController.h"
1616
#import "FLEXKeyboardHelpViewController.h"
1717
#import "FLEXFileBrowserController.h"
18+
#import "FLEXArgumentInputStructView.h"
1819
#import "FLEXUtility.h"
1920

2021
@interface FLEXManager (ExtensibilityPrivate)
@@ -75,6 +76,13 @@ - (void)clearGlobalEntries {
7576
}
7677

7778

79+
#pragma mark - Editing
80+
81+
+ (void)registerFieldNames:(NSArray<NSString *> *)names forTypeEncoding:(NSString *)typeEncoding {
82+
[FLEXArgumentInputStructView registerFieldNames:names forTypeEncoding:typeEncoding];
83+
}
84+
85+
7886
#pragma mark - Simulator Shortcuts
7987

8088
- (void)registerSimulatorShortcutWithKey:(NSString *)key modifiers:(UIKeyModifierFlags)modifiers action:(dispatch_block_t)action description:(NSString *)description {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//
2+
// FLEXMetadataExtras.h
3+
// FLEX
4+
//
5+
// Created by Tanner Bennett on 4/26/22.
6+
//
7+
8+
#import <Foundation/Foundation.h>
9+
#import "FLEXMethodBase.h"
10+
#import "FLEXProperty.h"
11+
#import "FLEXIvar.h"
12+
13+
NS_ASSUME_NONNULL_BEGIN
14+
15+
/// A dictionary mapping type encoding strings to an array of field titles
16+
extern NSString * const FLEXAuxiliarynfoKeyFieldLabels;
17+
18+
@protocol FLEXMetadataAuxiliaryInfo <NSObject>
19+
20+
/// Used to supply arbitrary additional data that need not be exposed by their own properties
21+
- (nullable id)auxiliaryInfoForKey:(NSString *)key;
22+
23+
@end
24+
25+
@interface FLEXMethodBase (Auxiliary) <FLEXMetadataAuxiliaryInfo> @end
26+
@interface FLEXProperty (Auxiliary) <FLEXMetadataAuxiliaryInfo> @end
27+
@interface FLEXIvar (Auxiliary) <FLEXMetadataAuxiliaryInfo> @end
28+
29+
30+
NS_ASSUME_NONNULL_END
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//
2+
// FLEXMetadataExtras.m
3+
// FLEX
4+
//
5+
// Created by Tanner Bennett on 4/26/22.
6+
//
7+
8+
#import "FLEXMetadataExtras.h"
9+
10+
NSString * const FLEXAuxiliarynfoKeyFieldLabels = @"FLEXAuxiliarynfoKeyFieldLabels";
11+
12+
@implementation FLEXMethodBase (Auxiliary)
13+
- (id)auxiliaryInfoForKey:(NSString *)key { return nil; }
14+
@end
15+
16+
@implementation FLEXProperty (Auxiliary)
17+
- (id)auxiliaryInfoForKey:(NSString *)key { return nil; }
18+
@end
19+
20+
@implementation FLEXIvar (Auxiliary)
21+
- (id)auxiliaryInfoForKey:(NSString *)key { return nil; }
22+
@end

FLEX.xcodeproj/project.pbxproj

+8
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,8 @@
264264
C387C87B22DFCD6A00750E58 /* FLEXCarouselCell.m in Sources */ = {isa = PBXBuildFile; fileRef = C387C87922DFCD6A00750E58 /* FLEXCarouselCell.m */; };
265265
C387C88322E0D24A00750E58 /* UIView+FLEX_Layout.h in Headers */ = {isa = PBXBuildFile; fileRef = C387C88122E0D24A00750E58 /* UIView+FLEX_Layout.h */; settings = {ATTRIBUTES = (Private, ); }; };
266266
C387C88422E0D24A00750E58 /* UIView+FLEX_Layout.m in Sources */ = {isa = PBXBuildFile; fileRef = C387C88222E0D24A00750E58 /* UIView+FLEX_Layout.m */; };
267+
C38D970228190C93008709D0 /* FLEXMetadataExtras.m in Sources */ = {isa = PBXBuildFile; fileRef = C38D970028190C93008709D0 /* FLEXMetadataExtras.m */; };
268+
C38D970328190C93008709D0 /* FLEXMetadataExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = C38D970128190C93008709D0 /* FLEXMetadataExtras.h */; };
267269
C38DF0EA22CFE4370077B4AD /* FLEXTableViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = C38DF0E822CFE4370077B4AD /* FLEXTableViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
268270
C38DF0EB22CFE4370077B4AD /* FLEXTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C38DF0E922CFE4370077B4AD /* FLEXTableViewController.m */; };
269271
C38EF26223A2FCD20047A7EC /* FLEXViewControllerShortcuts.m in Sources */ = {isa = PBXBuildFile; fileRef = C38EF26023A2FCD20047A7EC /* FLEXViewControllerShortcuts.m */; };
@@ -644,6 +646,8 @@
644646
C387C87922DFCD6A00750E58 /* FLEXCarouselCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLEXCarouselCell.m; sourceTree = "<group>"; };
645647
C387C88122E0D24A00750E58 /* UIView+FLEX_Layout.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIView+FLEX_Layout.h"; sourceTree = "<group>"; };
646648
C387C88222E0D24A00750E58 /* UIView+FLEX_Layout.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIView+FLEX_Layout.m"; sourceTree = "<group>"; };
649+
C38D970028190C93008709D0 /* FLEXMetadataExtras.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXMetadataExtras.m; sourceTree = "<group>"; };
650+
C38D970128190C93008709D0 /* FLEXMetadataExtras.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXMetadataExtras.h; sourceTree = "<group>"; };
647651
C38DF0E822CFE4370077B4AD /* FLEXTableViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FLEXTableViewController.h; sourceTree = "<group>"; };
648652
C38DF0E922CFE4370077B4AD /* FLEXTableViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLEXTableViewController.m; sourceTree = "<group>"; };
649653
C38EF26023A2FCD20047A7EC /* FLEXViewControllerShortcuts.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXViewControllerShortcuts.m; sourceTree = "<group>"; };
@@ -1282,6 +1286,8 @@
12821286
C36FBFC7230F3B98008D95D5 /* FLEXProtocolBuilder.m */,
12831287
C36FBFC9230F3B98008D95D5 /* FLEXClassBuilder.h */,
12841288
C36FBFBF230F3B98008D95D5 /* FLEXClassBuilder.m */,
1289+
C38D970128190C93008709D0 /* FLEXMetadataExtras.h */,
1290+
C38D970028190C93008709D0 /* FLEXMetadataExtras.m */,
12851291
);
12861292
path = Reflection;
12871293
sourceTree = "<group>";
@@ -1502,6 +1508,7 @@
15021508
3A4C94ED1B5B21410088C3F2 /* FLEXArgumentInputColorView.h in Headers */,
15031509
C3A9424523C641C1006871A3 /* SceneKit+Snapshot.h in Headers */,
15041510
3A4C94EB1B5B21410088C3F2 /* FLEXImagePreviewViewController.h in Headers */,
1511+
C38D970328190C93008709D0 /* FLEXMetadataExtras.h in Headers */,
15051512
C34D4EB823A2B17900C1F903 /* FLEXBundleShortcuts.h in Headers */,
15061513
C3694DC223EA147F006625D7 /* UIBarButtonItem+FLEX.h in Headers */,
15071514
C38F3F31230C958F004E3731 /* FLEXAlert.h in Headers */,
@@ -1827,6 +1834,7 @@
18271834
94AAF0391BAF2E1F00DE8760 /* FLEXKeyboardHelpViewController.m in Sources */,
18281835
C398624E23AD6C67007E6793 /* FLEXRuntimeKeyPath.m in Sources */,
18291836
C3694DC323EA147F006625D7 /* UIBarButtonItem+FLEX.m in Sources */,
1837+
C38D970228190C93008709D0 /* FLEXMetadataExtras.m in Sources */,
18301838
C36FBFD4230F3B98008D95D5 /* FLEXProtocol.m in Sources */,
18311839
C34D4EB123A2ABD900C1F903 /* FLEXLayerShortcuts.m in Sources */,
18321840
C38F3F32230C958F004E3731 /* FLEXAlert.m in Sources */,

0 commit comments

Comments
 (0)