|
@@ -20,6 +20,7 @@
|
|
|
#import "FLEXManager+Private.h"
|
|
#import "FLEXManager+Private.h"
|
|
|
#import "FLEXSystemLogTableViewController.h"
|
|
#import "FLEXSystemLogTableViewController.h"
|
|
|
#import "FLEXNetworkHistoryTableViewController.h"
|
|
#import "FLEXNetworkHistoryTableViewController.h"
|
|
|
|
|
+#import "FLEXAddressExplorerCoordinator.h"
|
|
|
|
|
|
|
|
static __weak UIWindow *s_applicationWindow = nil;
|
|
static __weak UIWindow *s_applicationWindow = nil;
|
|
|
|
|
|
|
@@ -51,240 +52,107 @@ typedef NS_ENUM(NSUInteger, FLEXGlobalsRow) {
|
|
|
|
|
|
|
|
@implementation FLEXGlobalsTableViewController
|
|
@implementation FLEXGlobalsTableViewController
|
|
|
|
|
|
|
|
-+ (NSArray<FLEXGlobalsTableViewControllerEntry *> *)defaultGlobalEntries
|
|
|
|
|
-{
|
|
|
|
|
- NSMutableArray<FLEXGlobalsTableViewControllerEntry *> *defaultGlobalEntries = [NSMutableArray array];
|
|
|
|
|
-
|
|
|
|
|
- for (FLEXGlobalsRow defaultRowIndex = 0; defaultRowIndex < FLEXGlobalsRowCount; defaultRowIndex++) {
|
|
|
|
|
- FLEXGlobalsTableViewControllerEntryNameFuture titleFuture = nil;
|
|
|
|
|
- FLEXGlobalsTableViewControllerViewControllerFuture viewControllerFuture = nil;
|
|
|
|
|
- FLEXGlobalsTableViewControllerRowAction rowAction = nil;
|
|
|
|
|
-
|
|
|
|
|
- switch (defaultRowIndex) {
|
|
|
|
|
- case FLEXGlobalsRowAppClasses: {
|
|
|
|
|
- titleFuture = ^NSString *{
|
|
|
|
|
- return [NSString stringWithFormat:@"📕 %@ Classes", [FLEXUtility applicationName]];
|
|
|
|
|
- };
|
|
|
|
|
- viewControllerFuture = ^UIViewController *{
|
|
|
|
|
- FLEXClassesTableViewController *classesViewController = [[FLEXClassesTableViewController alloc] init];
|
|
|
|
|
- classesViewController.binaryImageName = [FLEXUtility applicationImageName];
|
|
|
|
|
-
|
|
|
|
|
- return classesViewController;
|
|
|
|
|
- };
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- case FLEXGlobalsRowAddressInspector: {
|
|
|
|
|
- titleFuture = ^NSString *{
|
|
|
|
|
- return @"🔎 Address Explorer";
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- rowAction = ^(FLEXGlobalsTableViewController *host) {
|
|
|
|
|
- NSString *title = @"Explore Object at Address";
|
|
|
|
|
- NSString *message = @"Paste a hexadecimal address below, starting with '0x'. "
|
|
|
|
|
- "Use the unsafe option if you need to bypass pointer validation, "
|
|
|
|
|
- "but know that it may crash the app if the address is invalid.";
|
|
|
|
|
-
|
|
|
|
|
- UIAlertController *addressInput = [UIAlertController alertControllerWithTitle:title
|
|
|
|
|
- message:message
|
|
|
|
|
- preferredStyle:UIAlertControllerStyleAlert];
|
|
|
|
|
- void (^handler)(UIAlertAction *) = ^(UIAlertAction *action) {
|
|
|
|
|
- if (action.style == UIAlertActionStyleCancel) {
|
|
|
|
|
- [host deselectSelectedRow]; return;
|
|
|
|
|
- }
|
|
|
|
|
- NSString *address = addressInput.textFields.firstObject.text;
|
|
|
|
|
- [host tryExploreAddress:address safely:action.style == UIAlertActionStyleDefault];
|
|
|
|
|
- };
|
|
|
|
|
- [addressInput addTextFieldWithConfigurationHandler:^(UITextField *textField) {
|
|
|
|
|
- NSString *copied = [UIPasteboard generalPasteboard].string;
|
|
|
|
|
- textField.placeholder = @"0x00000070deadbeef";
|
|
|
|
|
- // Go ahead and paste our clipboard if we have an address copied
|
|
|
|
|
- if ([copied hasPrefix:@"0x"]) {
|
|
|
|
|
- textField.text = copied;
|
|
|
|
|
- [textField selectAll:nil];
|
|
|
|
|
- }
|
|
|
|
|
- }];
|
|
|
|
|
- [addressInput addAction:[UIAlertAction actionWithTitle:@"Explore"
|
|
|
|
|
- style:UIAlertActionStyleDefault
|
|
|
|
|
- handler:handler]];
|
|
|
|
|
- [addressInput addAction:[UIAlertAction actionWithTitle:@"Unsafe Explore"
|
|
|
|
|
- style:UIAlertActionStyleDestructive
|
|
|
|
|
- handler:handler]];
|
|
|
|
|
- [addressInput addAction:[UIAlertAction actionWithTitle:@"Cancel"
|
|
|
|
|
- style:UIAlertActionStyleCancel
|
|
|
|
|
- handler:handler]];
|
|
|
|
|
- [host presentViewController:addressInput animated:YES completion:nil];
|
|
|
|
|
- };
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- case FLEXGlobalsRowSystemLibraries: {
|
|
|
|
|
- NSString *titleString = @"📚 System Libraries";
|
|
|
|
|
- titleFuture = ^NSString *{
|
|
|
|
|
- return titleString;
|
|
|
|
|
- };
|
|
|
|
|
- viewControllerFuture = ^UIViewController *{
|
|
|
|
|
- FLEXLibrariesTableViewController *librariesViewController = [[FLEXLibrariesTableViewController alloc] init];
|
|
|
|
|
- librariesViewController.title = titleString;
|
|
|
|
|
-
|
|
|
|
|
- return librariesViewController;
|
|
|
|
|
- };
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- case FLEXGlobalsRowLiveObjects: {
|
|
|
|
|
- titleFuture = ^NSString *{
|
|
|
|
|
- return @"💩 Heap Objects";
|
|
|
|
|
- };
|
|
|
|
|
- viewControllerFuture = ^UIViewController *{
|
|
|
|
|
- return [[FLEXLiveObjectsTableViewController alloc] init];
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- case FLEXGlobalsRowAppDelegate: {
|
|
|
|
|
- titleFuture = ^NSString *{
|
|
|
|
|
- return [NSString stringWithFormat:@"👉 %@", [[[UIApplication sharedApplication] delegate] class]];
|
|
|
|
|
- };
|
|
|
|
|
- viewControllerFuture = ^UIViewController *{
|
|
|
|
|
- id <UIApplicationDelegate> appDelegate = [[UIApplication sharedApplication] delegate];
|
|
|
|
|
|
|
++ (FLEXGlobalsTableViewControllerEntry *)globalsEntryForRow:(FLEXGlobalsRow)row {
|
|
|
|
|
+ switch (row) {
|
|
|
|
|
+ case FLEXGlobalsRowAppClasses:
|
|
|
|
|
+ return [FLEXClassesTableViewController flex_concreteGlobalsEntry];
|
|
|
|
|
+ case FLEXGlobalsRowAddressInspector:
|
|
|
|
|
+ return [FLEXAddressExplorerCoordinator flex_concreteGlobalsEntry];
|
|
|
|
|
+ case FLEXGlobalsRowSystemLibraries:
|
|
|
|
|
+ return [FLEXLibrariesTableViewController flex_concreteGlobalsEntry];
|
|
|
|
|
+ case FLEXGlobalsRowLiveObjects:
|
|
|
|
|
+ return [FLEXLiveObjectsTableViewController flex_concreteGlobalsEntry];
|
|
|
|
|
+ case FLEXGlobalsCookies:
|
|
|
|
|
+ return [FLEXCookiesTableViewController flex_concreteGlobalsEntry];
|
|
|
|
|
+ case FLEXGlobalsRowFileBrowser:
|
|
|
|
|
+ return [FLEXFileBrowserTableViewController flex_concreteGlobalsEntry];
|
|
|
|
|
+ case FLEXGlobalsRowSystemLog:
|
|
|
|
|
+ return [FLEXSystemLogTableViewController flex_concreteGlobalsEntry];
|
|
|
|
|
+ case FLEXGlobalsRowNetworkHistory:
|
|
|
|
|
+ return [FLEXNetworkHistoryTableViewController flex_concreteGlobalsEntry];
|
|
|
|
|
+ case FLEXGlobalsRowAppDelegate:
|
|
|
|
|
+ return [FLEXGlobalsTableViewControllerEntry
|
|
|
|
|
+ entryWithNameFuture:^NSString *{
|
|
|
|
|
+ return [NSString stringWithFormat:@"👉 %@", [[UIApplication sharedApplication].delegate class]];
|
|
|
|
|
+ } viewControllerFuture:^UIViewController *{
|
|
|
|
|
+ id<UIApplicationDelegate> appDelegate = [UIApplication sharedApplication].delegate;
|
|
|
return [FLEXObjectExplorerFactory explorerViewControllerForObject:appDelegate];
|
|
return [FLEXObjectExplorerFactory explorerViewControllerForObject:appDelegate];
|
|
|
- };
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- case FLEXGlobalsRowRootViewController: {
|
|
|
|
|
- titleFuture = ^NSString *{
|
|
|
|
|
- return [NSString stringWithFormat:@"🌴 %@", [[s_applicationWindow rootViewController] class]];
|
|
|
|
|
- };
|
|
|
|
|
- viewControllerFuture = ^UIViewController *{
|
|
|
|
|
- UIViewController *rootViewController = [s_applicationWindow rootViewController];
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ ];
|
|
|
|
|
+ case FLEXGlobalsRowRootViewController:
|
|
|
|
|
+ return [FLEXGlobalsTableViewControllerEntry
|
|
|
|
|
+ entryWithNameFuture:^NSString *{
|
|
|
|
|
+ return [NSString stringWithFormat:@"🌴 %@", [s_applicationWindow.rootViewController class]];
|
|
|
|
|
+ } viewControllerFuture:^UIViewController *{
|
|
|
|
|
+ UIViewController *rootViewController = s_applicationWindow.rootViewController;
|
|
|
return [FLEXObjectExplorerFactory explorerViewControllerForObject:rootViewController];
|
|
return [FLEXObjectExplorerFactory explorerViewControllerForObject:rootViewController];
|
|
|
- };
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- case FLEXGlobalsRowUserDefaults: {
|
|
|
|
|
- titleFuture = ^NSString *{
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ ];
|
|
|
|
|
+ case FLEXGlobalsRowUserDefaults:
|
|
|
|
|
+ return [FLEXGlobalsTableViewControllerEntry
|
|
|
|
|
+ entryWithNameFuture:^NSString *{
|
|
|
return @"🚶 +[NSUserDefaults standardUserDefaults]";
|
|
return @"🚶 +[NSUserDefaults standardUserDefaults]";
|
|
|
- };
|
|
|
|
|
- viewControllerFuture = ^UIViewController *{
|
|
|
|
|
|
|
+ } viewControllerFuture:^UIViewController *{
|
|
|
NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults];
|
|
NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults];
|
|
|
return [FLEXObjectExplorerFactory explorerViewControllerForObject:standardUserDefaults];
|
|
return [FLEXObjectExplorerFactory explorerViewControllerForObject:standardUserDefaults];
|
|
|
- };
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- case FLEXGlobalsRowMainBundle: {
|
|
|
|
|
- titleFuture = ^NSString *{
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ ];
|
|
|
|
|
+ case FLEXGlobalsRowMainBundle:
|
|
|
|
|
+ return [FLEXGlobalsTableViewControllerEntry
|
|
|
|
|
+ entryWithNameFuture:^NSString *{
|
|
|
return @"📦 +[NSBundle mainBundle]";
|
|
return @"📦 +[NSBundle mainBundle]";
|
|
|
- };
|
|
|
|
|
- viewControllerFuture = ^UIViewController *{
|
|
|
|
|
|
|
+ } viewControllerFuture:^UIViewController *{
|
|
|
NSBundle *mainBundle = [NSBundle mainBundle];
|
|
NSBundle *mainBundle = [NSBundle mainBundle];
|
|
|
return [FLEXObjectExplorerFactory explorerViewControllerForObject:mainBundle];
|
|
return [FLEXObjectExplorerFactory explorerViewControllerForObject:mainBundle];
|
|
|
- };
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- case FLEXGlobalsRowApplication: {
|
|
|
|
|
- titleFuture = ^NSString *{
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ ];
|
|
|
|
|
+ case FLEXGlobalsRowApplication:
|
|
|
|
|
+ return [FLEXGlobalsTableViewControllerEntry
|
|
|
|
|
+ entryWithNameFuture:^NSString *{
|
|
|
return @"💾 +[UIApplication sharedApplication]";
|
|
return @"💾 +[UIApplication sharedApplication]";
|
|
|
- };
|
|
|
|
|
- viewControllerFuture = ^UIViewController *{
|
|
|
|
|
|
|
+ } viewControllerFuture:^UIViewController *{
|
|
|
UIApplication *sharedApplication = [UIApplication sharedApplication];
|
|
UIApplication *sharedApplication = [UIApplication sharedApplication];
|
|
|
return [FLEXObjectExplorerFactory explorerViewControllerForObject:sharedApplication];
|
|
return [FLEXObjectExplorerFactory explorerViewControllerForObject:sharedApplication];
|
|
|
- };
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- case FLEXGlobalsRowKeyWindow: {
|
|
|
|
|
- titleFuture = ^NSString *{
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ ];
|
|
|
|
|
+ case FLEXGlobalsRowKeyWindow:
|
|
|
|
|
+ return [FLEXGlobalsTableViewControllerEntry
|
|
|
|
|
+ entryWithNameFuture:^NSString *{
|
|
|
return @"🔑 -[UIApplication keyWindow]";
|
|
return @"🔑 -[UIApplication keyWindow]";
|
|
|
- };
|
|
|
|
|
- viewControllerFuture = ^UIViewController *{
|
|
|
|
|
|
|
+ } viewControllerFuture:^UIViewController *{
|
|
|
return [FLEXObjectExplorerFactory explorerViewControllerForObject:s_applicationWindow];
|
|
return [FLEXObjectExplorerFactory explorerViewControllerForObject:s_applicationWindow];
|
|
|
- };
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- case FLEXGlobalsRowMainScreen: {
|
|
|
|
|
- titleFuture = ^NSString *{
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ ];
|
|
|
|
|
+ case FLEXGlobalsRowMainScreen:
|
|
|
|
|
+ return [FLEXGlobalsTableViewControllerEntry
|
|
|
|
|
+ entryWithNameFuture:^NSString *{
|
|
|
return @"💻 +[UIScreen mainScreen]";
|
|
return @"💻 +[UIScreen mainScreen]";
|
|
|
- };
|
|
|
|
|
- viewControllerFuture = ^UIViewController *{
|
|
|
|
|
|
|
+ } viewControllerFuture:^UIViewController *{
|
|
|
UIScreen *mainScreen = [UIScreen mainScreen];
|
|
UIScreen *mainScreen = [UIScreen mainScreen];
|
|
|
return [FLEXObjectExplorerFactory explorerViewControllerForObject:mainScreen];
|
|
return [FLEXObjectExplorerFactory explorerViewControllerForObject:mainScreen];
|
|
|
- };
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ ];
|
|
|
|
|
|
|
|
- case FLEXGlobalsRowCurrentDevice: {
|
|
|
|
|
- titleFuture = ^NSString *{
|
|
|
|
|
|
|
+ case FLEXGlobalsRowCurrentDevice:
|
|
|
|
|
+ return [FLEXGlobalsTableViewControllerEntry
|
|
|
|
|
+ entryWithNameFuture:^NSString *{
|
|
|
return @"📱 +[UIDevice currentDevice]";
|
|
return @"📱 +[UIDevice currentDevice]";
|
|
|
- };
|
|
|
|
|
- viewControllerFuture = ^UIViewController *{
|
|
|
|
|
|
|
+ } viewControllerFuture:^UIViewController *{
|
|
|
UIDevice *currentDevice = [UIDevice currentDevice];
|
|
UIDevice *currentDevice = [UIDevice currentDevice];
|
|
|
return [FLEXObjectExplorerFactory explorerViewControllerForObject:currentDevice];
|
|
return [FLEXObjectExplorerFactory explorerViewControllerForObject:currentDevice];
|
|
|
- };
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- case FLEXGlobalsCookies: {
|
|
|
|
|
- titleFuture = ^NSString *{
|
|
|
|
|
- return @"🍪 Cookies";
|
|
|
|
|
- };
|
|
|
|
|
- viewControllerFuture = ^UIViewController *{
|
|
|
|
|
- return [[FLEXCookiesTableViewController alloc] init];
|
|
|
|
|
- };
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- case FLEXGlobalsRowFileBrowser: {
|
|
|
|
|
- titleFuture = ^NSString *{
|
|
|
|
|
- return @"📁 File Browser";
|
|
|
|
|
- };
|
|
|
|
|
- viewControllerFuture = ^UIViewController *{
|
|
|
|
|
- return [[FLEXFileBrowserTableViewController alloc] init];
|
|
|
|
|
- };
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ ];
|
|
|
|
|
|
|
|
- case FLEXGlobalsRowSystemLog: {
|
|
|
|
|
- titleFuture = ^{
|
|
|
|
|
- return @"⚠️ System Log";
|
|
|
|
|
- };
|
|
|
|
|
- viewControllerFuture = ^{
|
|
|
|
|
- return [[FLEXSystemLogTableViewController alloc] init];
|
|
|
|
|
- };
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- case FLEXGlobalsRowNetworkHistory: {
|
|
|
|
|
- titleFuture = ^{
|
|
|
|
|
- return @"📡 Network History";
|
|
|
|
|
- };
|
|
|
|
|
- viewControllerFuture = ^{
|
|
|
|
|
- return [[FLEXNetworkHistoryTableViewController alloc] init];
|
|
|
|
|
- };
|
|
|
|
|
- break;
|
|
|
|
|
- case FLEXGlobalsRowCount:
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- NSAssert(viewControllerFuture || rowAction, @"The switch-case above must assign one of these");
|
|
|
|
|
-
|
|
|
|
|
- if (viewControllerFuture) {
|
|
|
|
|
- [defaultGlobalEntries addObject:[FLEXGlobalsTableViewControllerEntry
|
|
|
|
|
- entryWithNameFuture:titleFuture
|
|
|
|
|
- viewControllerFuture:viewControllerFuture]];
|
|
|
|
|
- } else {
|
|
|
|
|
- [defaultGlobalEntries addObject:[FLEXGlobalsTableViewControllerEntry
|
|
|
|
|
- entryWithNameFuture:titleFuture
|
|
|
|
|
- action:rowAction]];
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ default:
|
|
|
|
|
+ @throw NSInternalInconsistencyException;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
|
|
++ (NSArray<FLEXGlobalsTableViewControllerEntry *> *)defaultGlobalEntries
|
|
|
|
|
+{
|
|
|
|
|
+ NSMutableArray<FLEXGlobalsTableViewControllerEntry *> *defaultGlobalEntries = [NSMutableArray array];
|
|
|
|
|
+ for (FLEXGlobalsRow defaultRowIndex = 0; defaultRowIndex < FLEXGlobalsRowCount; defaultRowIndex++) {
|
|
|
|
|
+ [defaultGlobalEntries addObject:[self globalsEntryForRow:defaultRowIndex]];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return defaultGlobalEntries;
|
|
return defaultGlobalEntries;
|
|
@@ -300,11 +168,6 @@ typedef NS_ENUM(NSUInteger, FLEXGlobalsRow) {
|
|
|
return self;
|
|
return self;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-- (void)deselectSelectedRow {
|
|
|
|
|
- NSIndexPath *selected = self.tableView.indexPathForSelectedRow;
|
|
|
|
|
- [self.tableView deselectRowAtIndexPath:selected animated:YES];
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
#pragma mark - Public
|
|
#pragma mark - Public
|
|
|
|
|
|
|
|
+ (void)setApplicationWindow:(UIWindow *)applicationWindow
|
|
+ (void)setApplicationWindow:(UIWindow *)applicationWindow
|
|
@@ -328,32 +191,6 @@ typedef NS_ENUM(NSUInteger, FLEXGlobalsRow) {
|
|
|
[self.delegate globalsViewControllerDidFinish:self];
|
|
[self.delegate globalsViewControllerDidFinish:self];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-- (void)tryExploreAddress:(NSString *)addressString safely:(BOOL)safely {
|
|
|
|
|
- NSScanner *scanner = [NSScanner scannerWithString:addressString];
|
|
|
|
|
- unsigned long long hexValue = 0;
|
|
|
|
|
- BOOL didParseAddress = [scanner scanHexLongLong:&hexValue];
|
|
|
|
|
- const void *pointerValue = (void *)hexValue;
|
|
|
|
|
-
|
|
|
|
|
- NSString *error = nil;
|
|
|
|
|
-
|
|
|
|
|
- if (didParseAddress) {
|
|
|
|
|
- if (safely && ![FLEXRuntimeUtility pointerIsValidObjcObject:pointerValue]) {
|
|
|
|
|
- error = @"The given address is unlikely to be a valid object.";
|
|
|
|
|
- }
|
|
|
|
|
- } else {
|
|
|
|
|
- error = @"Malformed address. Make sure it's not too long and starts with '0x'.";
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (!error) {
|
|
|
|
|
- id object = (__bridge id)pointerValue;
|
|
|
|
|
- FLEXObjectExplorerViewController *explorer = [FLEXObjectExplorerFactory explorerViewControllerForObject:object];
|
|
|
|
|
- [self.navigationController pushViewController:explorer animated:YES];
|
|
|
|
|
- } else {
|
|
|
|
|
- [FLEXUtility alert:@"Uh-oh" message:error from:self];
|
|
|
|
|
- [self deselectSelectedRow];
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
#pragma mark - Table Data Helpers
|
|
#pragma mark - Table Data Helpers
|
|
|
|
|
|
|
|
- (FLEXGlobalsTableViewControllerEntry *)globalEntryAtIndexPath:(NSIndexPath *)indexPath
|
|
- (FLEXGlobalsTableViewControllerEntry *)globalEntryAtIndexPath:(NSIndexPath *)indexPath
|