|
@@ -17,6 +17,20 @@
|
|
|
#import "FLEXInstancesTableViewController.h"
|
|
#import "FLEXInstancesTableViewController.h"
|
|
|
#import <objc/runtime.h>
|
|
#import <objc/runtime.h>
|
|
|
|
|
|
|
|
|
|
+typedef NS_ENUM(NSUInteger, FLEXObjectExplorerScope) {
|
|
|
|
|
+ FLEXObjectExplorerScopeNoInheritance,
|
|
|
|
|
+ FLEXObjectExplorerScopeWithParent,
|
|
|
|
|
+ FLEXObjectExplorerScopeAllButNSObject,
|
|
|
|
|
+ FLEXObjectExplorerScopeNSObjectOnly
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+typedef NS_ENUM(NSUInteger, FLEXMetadataKind) {
|
|
|
|
|
+ FLEXMetadataKindProperties,
|
|
|
|
|
+ FLEXMetadataKindIvars,
|
|
|
|
|
+ FLEXMetadataKindMethods,
|
|
|
|
|
+ FLEXMetadataKindClassMethods
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
// Convenience boxes to keep runtime properties, ivars, and methods in foundation collections.
|
|
// Convenience boxes to keep runtime properties, ivars, and methods in foundation collections.
|
|
|
@interface FLEXPropertyBox : NSObject
|
|
@interface FLEXPropertyBox : NSObject
|
|
|
@property (nonatomic, assign) objc_property_t property;
|
|
@property (nonatomic, assign) objc_property_t property;
|
|
@@ -36,25 +50,30 @@
|
|
|
@implementation FLEXMethodBox
|
|
@implementation FLEXMethodBox
|
|
|
@end
|
|
@end
|
|
|
|
|
|
|
|
-static const NSInteger kFLEXObjectExplorerScopeNoInheritanceIndex = 0;
|
|
|
|
|
-static const NSInteger kFLEXObjectExplorerScopeIncludeInheritanceIndex = 1;
|
|
|
|
|
-
|
|
|
|
|
@interface FLEXObjectExplorerViewController () <UISearchBarDelegate>
|
|
@interface FLEXObjectExplorerViewController () <UISearchBarDelegate>
|
|
|
|
|
|
|
|
@property (nonatomic, strong) NSArray<FLEXPropertyBox *> *properties;
|
|
@property (nonatomic, strong) NSArray<FLEXPropertyBox *> *properties;
|
|
|
|
|
+@property (nonatomic, strong) NSArray<FLEXPropertyBox *> *propertiesWithParent;
|
|
|
@property (nonatomic, strong) NSArray<FLEXPropertyBox *> *inheritedProperties;
|
|
@property (nonatomic, strong) NSArray<FLEXPropertyBox *> *inheritedProperties;
|
|
|
|
|
+@property (nonatomic, strong) NSArray<FLEXPropertyBox *> *NSObjectProperties;
|
|
|
@property (nonatomic, strong) NSArray<FLEXPropertyBox *> *filteredProperties;
|
|
@property (nonatomic, strong) NSArray<FLEXPropertyBox *> *filteredProperties;
|
|
|
|
|
|
|
|
@property (nonatomic, strong) NSArray<FLEXIvarBox *> *ivars;
|
|
@property (nonatomic, strong) NSArray<FLEXIvarBox *> *ivars;
|
|
|
|
|
+@property (nonatomic, strong) NSArray<FLEXIvarBox *> *ivarsWithParent;
|
|
|
@property (nonatomic, strong) NSArray<FLEXIvarBox *> *inheritedIvars;
|
|
@property (nonatomic, strong) NSArray<FLEXIvarBox *> *inheritedIvars;
|
|
|
|
|
+@property (nonatomic, strong) NSArray<FLEXIvarBox *> *NSObjectIvars;
|
|
|
@property (nonatomic, strong) NSArray<FLEXIvarBox *> *filteredIvars;
|
|
@property (nonatomic, strong) NSArray<FLEXIvarBox *> *filteredIvars;
|
|
|
|
|
|
|
|
@property (nonatomic, strong) NSArray<FLEXMethodBox *> *methods;
|
|
@property (nonatomic, strong) NSArray<FLEXMethodBox *> *methods;
|
|
|
|
|
+@property (nonatomic, strong) NSArray<FLEXMethodBox *> *methodsWithParent;
|
|
|
@property (nonatomic, strong) NSArray<FLEXMethodBox *> *inheritedMethods;
|
|
@property (nonatomic, strong) NSArray<FLEXMethodBox *> *inheritedMethods;
|
|
|
|
|
+@property (nonatomic, strong) NSArray<FLEXMethodBox *> *NSObjectMethods;
|
|
|
@property (nonatomic, strong) NSArray<FLEXMethodBox *> *filteredMethods;
|
|
@property (nonatomic, strong) NSArray<FLEXMethodBox *> *filteredMethods;
|
|
|
|
|
|
|
|
@property (nonatomic, strong) NSArray<FLEXMethodBox *> *classMethods;
|
|
@property (nonatomic, strong) NSArray<FLEXMethodBox *> *classMethods;
|
|
|
|
|
+@property (nonatomic, strong) NSArray<FLEXMethodBox *> *classMethodsWithParent;
|
|
|
@property (nonatomic, strong) NSArray<FLEXMethodBox *> *inheritedClassMethods;
|
|
@property (nonatomic, strong) NSArray<FLEXMethodBox *> *inheritedClassMethods;
|
|
|
|
|
+@property (nonatomic, strong) NSArray<FLEXMethodBox *> *NSObjectClassMethods;
|
|
|
@property (nonatomic, strong) NSArray<FLEXMethodBox *> *filteredClassMethods;
|
|
@property (nonatomic, strong) NSArray<FLEXMethodBox *> *filteredClassMethods;
|
|
|
|
|
|
|
|
@property (nonatomic, strong) NSArray<Class> *superclasses;
|
|
@property (nonatomic, strong) NSArray<Class> *superclasses;
|
|
@@ -65,7 +84,7 @@ static const NSInteger kFLEXObjectExplorerScopeIncludeInheritanceIndex = 1;
|
|
|
|
|
|
|
|
@property (nonatomic, strong) UISearchBar *searchBar;
|
|
@property (nonatomic, strong) UISearchBar *searchBar;
|
|
|
@property (nonatomic, strong) NSString *filterText;
|
|
@property (nonatomic, strong) NSString *filterText;
|
|
|
-@property (nonatomic, assign) BOOL includeInheritance;
|
|
|
|
|
|
|
+@property (nonatomic, assign) FLEXObjectExplorerScope scope;
|
|
|
|
|
|
|
|
@end
|
|
@end
|
|
|
|
|
|
|
@@ -85,8 +104,7 @@ static const NSInteger kFLEXObjectExplorerScopeIncludeInheritanceIndex = 1;
|
|
|
self.searchBar.placeholder = [FLEXUtility searchBarPlaceholderText];
|
|
self.searchBar.placeholder = [FLEXUtility searchBarPlaceholderText];
|
|
|
self.searchBar.delegate = self;
|
|
self.searchBar.delegate = self;
|
|
|
self.searchBar.showsScopeBar = YES;
|
|
self.searchBar.showsScopeBar = YES;
|
|
|
- self.searchBar.scopeButtonTitles = @[@"No Inheritance", @"Include Inheritance"];
|
|
|
|
|
- [self.searchBar sizeToFit];
|
|
|
|
|
|
|
+ [self refreshScopeTitles];
|
|
|
self.tableView.tableHeaderView = self.searchBar;
|
|
self.tableView.tableHeaderView = self.searchBar;
|
|
|
|
|
|
|
|
self.refreshControl = [[UIRefreshControl alloc] init];
|
|
self.refreshControl = [[UIRefreshControl alloc] init];
|
|
@@ -116,6 +134,28 @@ static const NSInteger kFLEXObjectExplorerScopeIncludeInheritanceIndex = 1;
|
|
|
|
|
|
|
|
#pragma mark - Search
|
|
#pragma mark - Search
|
|
|
|
|
|
|
|
|
|
+- (void)refreshScopeTitles {
|
|
|
|
|
+ if (!self.searchBar) return;
|
|
|
|
|
+
|
|
|
|
|
+ Class parent = [self.object superclass];
|
|
|
|
|
+ Class parentSuper = [parent superclass];
|
|
|
|
|
+
|
|
|
|
|
+ NSMutableArray *scopes = [NSMutableArray arrayWithObject:@"Base"];
|
|
|
|
|
+ if (parent) {
|
|
|
|
|
+ [scopes addObject:@"+ Parent"];
|
|
|
|
|
+ }
|
|
|
|
|
+ if (parentSuper && parentSuper != [NSObject class]) {
|
|
|
|
|
+ [scopes addObject:@"+ Inherited"];
|
|
|
|
|
+ }
|
|
|
|
|
+ if ([self.object isKindOfClass:[NSObject class]]) {
|
|
|
|
|
+ [scopes addObject:@"NSObject"];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ self.searchBar.scopeButtonTitles = scopes;
|
|
|
|
|
+ [self.searchBar sizeToFit];
|
|
|
|
|
+ [self updateTableData];
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
|
|
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
|
|
|
{
|
|
{
|
|
|
self.filterText = searchText;
|
|
self.filterText = searchText;
|
|
@@ -128,13 +168,62 @@ static const NSInteger kFLEXObjectExplorerScopeIncludeInheritanceIndex = 1;
|
|
|
|
|
|
|
|
- (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope
|
|
- (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope
|
|
|
{
|
|
{
|
|
|
- if (selectedScope == kFLEXObjectExplorerScopeIncludeInheritanceIndex) {
|
|
|
|
|
- self.includeInheritance = YES;
|
|
|
|
|
- } else if (selectedScope == kFLEXObjectExplorerScopeNoInheritanceIndex) {
|
|
|
|
|
- self.includeInheritance = NO;
|
|
|
|
|
|
|
+ self.scope = selectedScope;
|
|
|
|
|
+ [self updateDisplayedData];
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+- (NSArray *)metadata:(FLEXMetadataKind)metadataKind forScope:(FLEXObjectExplorerScope)scope {
|
|
|
|
|
+ switch (metadataKind) {
|
|
|
|
|
+ case FLEXMetadataKindProperties:
|
|
|
|
|
+ switch (self.scope) {
|
|
|
|
|
+ case FLEXObjectExplorerScopeNoInheritance:
|
|
|
|
|
+ return self.properties;
|
|
|
|
|
+ case FLEXObjectExplorerScopeWithParent:
|
|
|
|
|
+ return self.propertiesWithParent;
|
|
|
|
|
+ case FLEXObjectExplorerScopeAllButNSObject:
|
|
|
|
|
+ return self.inheritedProperties;
|
|
|
|
|
+ case FLEXObjectExplorerScopeNSObjectOnly:
|
|
|
|
|
+ return self.NSObjectProperties;
|
|
|
|
|
+ }
|
|
|
|
|
+ case FLEXMetadataKindIvars:
|
|
|
|
|
+ switch (self.scope) {
|
|
|
|
|
+ case FLEXObjectExplorerScopeNoInheritance:
|
|
|
|
|
+ return self.ivars;
|
|
|
|
|
+ case FLEXObjectExplorerScopeWithParent:
|
|
|
|
|
+ return self.ivarsWithParent;
|
|
|
|
|
+ case FLEXObjectExplorerScopeAllButNSObject:
|
|
|
|
|
+ return self.inheritedIvars;
|
|
|
|
|
+ case FLEXObjectExplorerScopeNSObjectOnly:
|
|
|
|
|
+ return self.NSObjectIvars;
|
|
|
|
|
+ }
|
|
|
|
|
+ case FLEXMetadataKindMethods:
|
|
|
|
|
+ switch (self.scope) {
|
|
|
|
|
+ case FLEXObjectExplorerScopeNoInheritance:
|
|
|
|
|
+ return self.methods;
|
|
|
|
|
+ case FLEXObjectExplorerScopeWithParent:
|
|
|
|
|
+ return self.methodsWithParent;
|
|
|
|
|
+ case FLEXObjectExplorerScopeAllButNSObject:
|
|
|
|
|
+ return self.inheritedMethods;
|
|
|
|
|
+ case FLEXObjectExplorerScopeNSObjectOnly:
|
|
|
|
|
+ return self.NSObjectMethods;
|
|
|
|
|
+ }
|
|
|
|
|
+ case FLEXMetadataKindClassMethods:
|
|
|
|
|
+ switch (self.scope) {
|
|
|
|
|
+ case FLEXObjectExplorerScopeNoInheritance:
|
|
|
|
|
+ return self.classMethods;
|
|
|
|
|
+ case FLEXObjectExplorerScopeWithParent:
|
|
|
|
|
+ return self.classMethodsWithParent;
|
|
|
|
|
+ case FLEXObjectExplorerScopeAllButNSObject:
|
|
|
|
|
+ return self.inheritedClassMethods;
|
|
|
|
|
+ case FLEXObjectExplorerScopeNSObjectOnly:
|
|
|
|
|
+ return self.NSObjectClassMethods;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+- (NSInteger)totalCountOfMetadata:(FLEXMetadataKind)metadataKind forScope:(FLEXObjectExplorerScope)scope {
|
|
|
|
|
+ return [self metadata:metadataKind forScope:scope].count;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
#pragma mark - Setter overrides
|
|
#pragma mark - Setter overrides
|
|
|
|
|
|
|
@@ -143,15 +232,7 @@ static const NSInteger kFLEXObjectExplorerScopeIncludeInheritanceIndex = 1;
|
|
|
_object = object;
|
|
_object = object;
|
|
|
// Use [object class] here rather than object_getClass because we don't want to show the KVO prefix for observed objects.
|
|
// Use [object class] here rather than object_getClass because we don't want to show the KVO prefix for observed objects.
|
|
|
self.title = [[object class] description];
|
|
self.title = [[object class] description];
|
|
|
- [self updateTableData];
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-- (void)setIncludeInheritance:(BOOL)includeInheritance
|
|
|
|
|
-{
|
|
|
|
|
- if (_includeInheritance != includeInheritance) {
|
|
|
|
|
- _includeInheritance = includeInheritance;
|
|
|
|
|
- [self updateDisplayedData];
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ [self refreshScopeTitles];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- (void)setFilterText:(NSString *)filterText
|
|
- (void)setFilterText:(NSString *)filterText
|
|
@@ -215,11 +296,17 @@ static const NSInteger kFLEXObjectExplorerScopeIncludeInheritanceIndex = 1;
|
|
|
{
|
|
{
|
|
|
Class class = [self.object class];
|
|
Class class = [self.object class];
|
|
|
self.properties = [[self class] propertiesForClass:class];
|
|
self.properties = [[self class] propertiesForClass:class];
|
|
|
- self.inheritedProperties = [[self class] inheritedPropertiesForClass:class];
|
|
|
|
|
|
|
+ self.propertiesWithParent = [self.properties arrayByAddingObjectsFromArray:[[self class] propertiesForClass:[class superclass]]];
|
|
|
|
|
+ self.inheritedProperties = [self.properties arrayByAddingObjectsFromArray:[[self class] inheritedPropertiesForClass:class]];
|
|
|
|
|
+ self.NSObjectProperties = [[self class] propertiesForClass:[NSObject class]];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ (NSArray<FLEXPropertyBox *> *)propertiesForClass:(Class)class
|
|
+ (NSArray<FLEXPropertyBox *> *)propertiesForClass:(Class)class
|
|
|
{
|
|
{
|
|
|
|
|
+ if (!class) {
|
|
|
|
|
+ return @[];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
NSMutableArray<FLEXPropertyBox *> *boxedProperties = [NSMutableArray array];
|
|
NSMutableArray<FLEXPropertyBox *> *boxedProperties = [NSMutableArray array];
|
|
|
unsigned int propertyCount = 0;
|
|
unsigned int propertyCount = 0;
|
|
|
objc_property_t *propertyList = class_copyPropertyList(class, &propertyCount);
|
|
objc_property_t *propertyList = class_copyPropertyList(class, &propertyCount);
|
|
@@ -234,10 +321,11 @@ static const NSInteger kFLEXObjectExplorerScopeIncludeInheritanceIndex = 1;
|
|
|
return boxedProperties;
|
|
return boxedProperties;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/// Skips NSObject
|
|
|
+ (NSArray<FLEXPropertyBox *> *)inheritedPropertiesForClass:(Class)class
|
|
+ (NSArray<FLEXPropertyBox *> *)inheritedPropertiesForClass:(Class)class
|
|
|
{
|
|
{
|
|
|
NSMutableArray<FLEXPropertyBox *> *inheritedProperties = [NSMutableArray array];
|
|
NSMutableArray<FLEXPropertyBox *> *inheritedProperties = [NSMutableArray array];
|
|
|
- while ((class = [class superclass])) {
|
|
|
|
|
|
|
+ while ((class = [class superclass]) && class != [NSObject class]) {
|
|
|
[inheritedProperties addObjectsFromArray:[self propertiesForClass:class]];
|
|
[inheritedProperties addObjectsFromArray:[self propertiesForClass:class]];
|
|
|
}
|
|
}
|
|
|
return inheritedProperties;
|
|
return inheritedProperties;
|
|
@@ -245,10 +333,7 @@ static const NSInteger kFLEXObjectExplorerScopeIncludeInheritanceIndex = 1;
|
|
|
|
|
|
|
|
- (void)updateFilteredProperties
|
|
- (void)updateFilteredProperties
|
|
|
{
|
|
{
|
|
|
- NSArray<FLEXPropertyBox *> *candidateProperties = self.properties;
|
|
|
|
|
- if (self.includeInheritance) {
|
|
|
|
|
- candidateProperties = [candidateProperties arrayByAddingObjectsFromArray:self.inheritedProperties];
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ NSArray<FLEXPropertyBox *> *candidateProperties = [self metadata:FLEXMetadataKindProperties forScope:self.scope];
|
|
|
|
|
|
|
|
NSArray<FLEXPropertyBox *> *unsortedFilteredProperties = nil;
|
|
NSArray<FLEXPropertyBox *> *unsortedFilteredProperties = nil;
|
|
|
if ([self.filterText length] > 0) {
|
|
if ([self.filterText length] > 0) {
|
|
@@ -294,11 +379,16 @@ static const NSInteger kFLEXObjectExplorerScopeIncludeInheritanceIndex = 1;
|
|
|
{
|
|
{
|
|
|
Class class = [self.object class];
|
|
Class class = [self.object class];
|
|
|
self.ivars = [[self class] ivarsForClass:class];
|
|
self.ivars = [[self class] ivarsForClass:class];
|
|
|
- self.inheritedIvars = [[self class] inheritedIvarsForClass:class];
|
|
|
|
|
|
|
+ self.ivarsWithParent = [self.ivars arrayByAddingObjectsFromArray:[[self class] ivarsForClass:[class superclass]]];
|
|
|
|
|
+ self.inheritedIvars = [self.ivars arrayByAddingObjectsFromArray:[[self class] inheritedIvarsForClass:class]];
|
|
|
|
|
+ self.NSObjectIvars = [[self class] ivarsForClass:[NSObject class]];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ (NSArray<FLEXIvarBox *> *)ivarsForClass:(Class)class
|
|
+ (NSArray<FLEXIvarBox *> *)ivarsForClass:(Class)class
|
|
|
{
|
|
{
|
|
|
|
|
+ if (!class) {
|
|
|
|
|
+ return @[];
|
|
|
|
|
+ }
|
|
|
NSMutableArray<FLEXIvarBox *> *boxedIvars = [NSMutableArray array];
|
|
NSMutableArray<FLEXIvarBox *> *boxedIvars = [NSMutableArray array];
|
|
|
unsigned int ivarCount = 0;
|
|
unsigned int ivarCount = 0;
|
|
|
Ivar *ivarList = class_copyIvarList(class, &ivarCount);
|
|
Ivar *ivarList = class_copyIvarList(class, &ivarCount);
|
|
@@ -313,10 +403,11 @@ static const NSInteger kFLEXObjectExplorerScopeIncludeInheritanceIndex = 1;
|
|
|
return boxedIvars;
|
|
return boxedIvars;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/// Skips NSObject
|
|
|
+ (NSArray<FLEXIvarBox *> *)inheritedIvarsForClass:(Class)class
|
|
+ (NSArray<FLEXIvarBox *> *)inheritedIvarsForClass:(Class)class
|
|
|
{
|
|
{
|
|
|
NSMutableArray<FLEXIvarBox *> *inheritedIvars = [NSMutableArray array];
|
|
NSMutableArray<FLEXIvarBox *> *inheritedIvars = [NSMutableArray array];
|
|
|
- while ((class = [class superclass])) {
|
|
|
|
|
|
|
+ while ((class = [class superclass]) && class != [NSObject class]) {
|
|
|
[inheritedIvars addObjectsFromArray:[self ivarsForClass:class]];
|
|
[inheritedIvars addObjectsFromArray:[self ivarsForClass:class]];
|
|
|
}
|
|
}
|
|
|
return inheritedIvars;
|
|
return inheritedIvars;
|
|
@@ -324,10 +415,7 @@ static const NSInteger kFLEXObjectExplorerScopeIncludeInheritanceIndex = 1;
|
|
|
|
|
|
|
|
- (void)updateFilteredIvars
|
|
- (void)updateFilteredIvars
|
|
|
{
|
|
{
|
|
|
- NSArray<FLEXIvarBox *> *candidateIvars = self.ivars;
|
|
|
|
|
- if (self.includeInheritance) {
|
|
|
|
|
- candidateIvars = [candidateIvars arrayByAddingObjectsFromArray:self.inheritedIvars];
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ NSArray<FLEXIvarBox *> *candidateIvars = [self metadata:FLEXMetadataKindIvars forScope:self.scope];
|
|
|
|
|
|
|
|
NSArray<FLEXIvarBox *> *unsortedFilteredIvars = nil;
|
|
NSArray<FLEXIvarBox *> *unsortedFilteredIvars = nil;
|
|
|
if ([self.filterText length] > 0) {
|
|
if ([self.filterText length] > 0) {
|
|
@@ -373,12 +461,15 @@ static const NSInteger kFLEXObjectExplorerScopeIncludeInheritanceIndex = 1;
|
|
|
{
|
|
{
|
|
|
Class class = [self.object class];
|
|
Class class = [self.object class];
|
|
|
self.methods = [[self class] methodsForClass:class];
|
|
self.methods = [[self class] methodsForClass:class];
|
|
|
- self.inheritedMethods = [[self class] inheritedMethodsForClass:class];
|
|
|
|
|
|
|
+ self.methodsWithParent = [self.methods arrayByAddingObjectsFromArray:[[self class] methodsForClass:[class superclass]]];
|
|
|
|
|
+ self.inheritedMethods = [self.methods arrayByAddingObjectsFromArray:[[self class] inheritedMethodsForClass:class]];
|
|
|
|
|
+ self.NSObjectMethods = [[self class] methodsForClass:[NSObject class]];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- (void)updateFilteredMethods
|
|
- (void)updateFilteredMethods
|
|
|
{
|
|
{
|
|
|
- self.filteredMethods = [self filteredMethodsFromMethods:self.methods inheritedMethods:self.inheritedMethods areClassMethods:NO];
|
|
|
|
|
|
|
+ NSArray<FLEXMethodBox *> *candidateMethods = [self metadata:FLEXMetadataKindMethods forScope:self.scope];
|
|
|
|
|
+ self.filteredMethods = [self filteredMethodsFromMethods:candidateMethods areClassMethods:NO];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- (void)updateClassMethods
|
|
- (void)updateClassMethods
|
|
@@ -386,16 +477,23 @@ static const NSInteger kFLEXObjectExplorerScopeIncludeInheritanceIndex = 1;
|
|
|
const char *className = [NSStringFromClass([self.object class]) UTF8String];
|
|
const char *className = [NSStringFromClass([self.object class]) UTF8String];
|
|
|
Class metaClass = objc_getMetaClass(className);
|
|
Class metaClass = objc_getMetaClass(className);
|
|
|
self.classMethods = [[self class] methodsForClass:metaClass];
|
|
self.classMethods = [[self class] methodsForClass:metaClass];
|
|
|
- self.inheritedClassMethods = [[self class] inheritedMethodsForClass:metaClass];
|
|
|
|
|
|
|
+ self.classMethodsWithParent = [self.classMethods arrayByAddingObjectsFromArray:[[self class] methodsForClass:[metaClass superclass]]];
|
|
|
|
|
+ self.inheritedClassMethods = [self.classMethods arrayByAddingObjectsFromArray:[[self class] inheritedMethodsForClass:metaClass]];
|
|
|
|
|
+ self.NSObjectClassMethods = [[self class] methodsForClass:[NSObject class]];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- (void)updateFilteredClassMethods
|
|
- (void)updateFilteredClassMethods
|
|
|
{
|
|
{
|
|
|
- self.filteredClassMethods = [self filteredMethodsFromMethods:self.classMethods inheritedMethods:self.inheritedClassMethods areClassMethods:YES];
|
|
|
|
|
|
|
+ NSArray<FLEXMethodBox *> *candidateMethods = [self metadata:FLEXMetadataKindClassMethods forScope:self.scope];
|
|
|
|
|
+ self.filteredClassMethods = [self filteredMethodsFromMethods:candidateMethods areClassMethods:YES];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ (NSArray<FLEXMethodBox *> *)methodsForClass:(Class)class
|
|
+ (NSArray<FLEXMethodBox *> *)methodsForClass:(Class)class
|
|
|
{
|
|
{
|
|
|
|
|
+ if (!class) {
|
|
|
|
|
+ return @[];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
NSMutableArray<FLEXMethodBox *> *boxedMethods = [NSMutableArray array];
|
|
NSMutableArray<FLEXMethodBox *> *boxedMethods = [NSMutableArray array];
|
|
|
unsigned int methodCount = 0;
|
|
unsigned int methodCount = 0;
|
|
|
Method *methodList = class_copyMethodList(class, &methodCount);
|
|
Method *methodList = class_copyMethodList(class, &methodCount);
|
|
@@ -410,22 +508,19 @@ static const NSInteger kFLEXObjectExplorerScopeIncludeInheritanceIndex = 1;
|
|
|
return boxedMethods;
|
|
return boxedMethods;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/// Skips NSObject
|
|
|
+ (NSArray<FLEXMethodBox *> *)inheritedMethodsForClass:(Class)class
|
|
+ (NSArray<FLEXMethodBox *> *)inheritedMethodsForClass:(Class)class
|
|
|
{
|
|
{
|
|
|
NSMutableArray<FLEXMethodBox *> *inheritedMethods = [NSMutableArray array];
|
|
NSMutableArray<FLEXMethodBox *> *inheritedMethods = [NSMutableArray array];
|
|
|
- while ((class = [class superclass])) {
|
|
|
|
|
|
|
+ while ((class = [class superclass]) && class != [NSObject class]) {
|
|
|
[inheritedMethods addObjectsFromArray:[self methodsForClass:class]];
|
|
[inheritedMethods addObjectsFromArray:[self methodsForClass:class]];
|
|
|
}
|
|
}
|
|
|
return inheritedMethods;
|
|
return inheritedMethods;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-- (NSArray<FLEXMethodBox *> *)filteredMethodsFromMethods:(NSArray<FLEXMethodBox *> *)methods inheritedMethods:(NSArray<FLEXMethodBox *> *)inheritedMethods areClassMethods:(BOOL)areClassMethods
|
|
|
|
|
|
|
+- (NSArray<FLEXMethodBox *> *)filteredMethodsFromMethods:(NSArray<FLEXMethodBox *> *)methods areClassMethods:(BOOL)areClassMethods
|
|
|
{
|
|
{
|
|
|
NSArray<FLEXMethodBox *> *candidateMethods = methods;
|
|
NSArray<FLEXMethodBox *> *candidateMethods = methods;
|
|
|
- if (self.includeInheritance) {
|
|
|
|
|
- candidateMethods = [candidateMethods arrayByAddingObjectsFromArray:inheritedMethods];
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
NSArray<FLEXMethodBox *> *unsortedFilteredMethods = nil;
|
|
NSArray<FLEXMethodBox *> *unsortedFilteredMethods = nil;
|
|
|
if ([self.filterText length] > 0) {
|
|
if ([self.filterText length] > 0) {
|
|
|
NSMutableArray<FLEXMethodBox *> *mutableUnsortedFilteredMethods = [NSMutableArray array];
|
|
NSMutableArray<FLEXMethodBox *> *mutableUnsortedFilteredMethods = [NSMutableArray array];
|
|
@@ -736,34 +831,22 @@ static const NSInteger kFLEXObjectExplorerScopeIncludeInheritanceIndex = 1;
|
|
|
} break;
|
|
} break;
|
|
|
|
|
|
|
|
case FLEXObjectExplorerSectionProperties: {
|
|
case FLEXObjectExplorerSectionProperties: {
|
|
|
- NSUInteger totalCount = [self.properties count];
|
|
|
|
|
- if (self.includeInheritance) {
|
|
|
|
|
- totalCount += [self.inheritedProperties count];
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ NSUInteger totalCount = [self totalCountOfMetadata:FLEXMetadataKindProperties forScope:self.scope];
|
|
|
title = [self sectionTitleWithBaseName:@"Properties" totalCount:totalCount filteredCount:[self.filteredProperties count]];
|
|
title = [self sectionTitleWithBaseName:@"Properties" totalCount:totalCount filteredCount:[self.filteredProperties count]];
|
|
|
} break;
|
|
} break;
|
|
|
|
|
|
|
|
case FLEXObjectExplorerSectionIvars: {
|
|
case FLEXObjectExplorerSectionIvars: {
|
|
|
- NSUInteger totalCount = [self.ivars count];
|
|
|
|
|
- if (self.includeInheritance) {
|
|
|
|
|
- totalCount += [self.inheritedIvars count];
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ NSUInteger totalCount = [self totalCountOfMetadata:FLEXMetadataKindIvars forScope:self.scope];
|
|
|
title = [self sectionTitleWithBaseName:@"Ivars" totalCount:totalCount filteredCount:[self.filteredIvars count]];
|
|
title = [self sectionTitleWithBaseName:@"Ivars" totalCount:totalCount filteredCount:[self.filteredIvars count]];
|
|
|
} break;
|
|
} break;
|
|
|
|
|
|
|
|
case FLEXObjectExplorerSectionMethods: {
|
|
case FLEXObjectExplorerSectionMethods: {
|
|
|
- NSUInteger totalCount = [self.methods count];
|
|
|
|
|
- if (self.includeInheritance) {
|
|
|
|
|
- totalCount += [self.inheritedMethods count];
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ NSUInteger totalCount = [self totalCountOfMetadata:FLEXMetadataKindMethods forScope:self.scope];
|
|
|
title = [self sectionTitleWithBaseName:@"Methods" totalCount:totalCount filteredCount:[self.filteredMethods count]];
|
|
title = [self sectionTitleWithBaseName:@"Methods" totalCount:totalCount filteredCount:[self.filteredMethods count]];
|
|
|
} break;
|
|
} break;
|
|
|
|
|
|
|
|
case FLEXObjectExplorerSectionClassMethods: {
|
|
case FLEXObjectExplorerSectionClassMethods: {
|
|
|
- NSUInteger totalCount = [self.classMethods count];
|
|
|
|
|
- if (self.includeInheritance) {
|
|
|
|
|
- totalCount += [self.inheritedClassMethods count];
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ NSUInteger totalCount = [self totalCountOfMetadata:FLEXMetadataKindClassMethods forScope:self.scope];
|
|
|
title = [self sectionTitleWithBaseName:@"Class Methods" totalCount:totalCount filteredCount:[self.filteredClassMethods count]];
|
|
title = [self sectionTitleWithBaseName:@"Class Methods" totalCount:totalCount filteredCount:[self.filteredClassMethods count]];
|
|
|
} break;
|
|
} break;
|
|
|
|
|
|