FLEXObjcRuntimeViewController.m 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. //
  2. // FLEXObjcRuntimeViewController.m
  3. // FLEX
  4. //
  5. // Created by Tanner on 3/23/17.
  6. // Copyright © 2017 Tanner Bennett. All rights reserved.
  7. //
  8. #import "FLEXObjcRuntimeViewController.h"
  9. #import "FLEXKeyPathSearchController.h"
  10. #import "FLEXRuntimeBrowserToolbar.h"
  11. #import "UIGestureRecognizer+Blocks.h"
  12. #import "FLEXTableView.h"
  13. #import "FLEXObjectExplorerFactory.h"
  14. #import "FLEXAlert.h"
  15. #import "FLEXRuntimeClient.h"
  16. @interface FLEXObjcRuntimeViewController () <FLEXKeyPathSearchControllerDelegate>
  17. @property (nonatomic, readonly ) FLEXKeyPathSearchController *keyPathController;
  18. @property (nonatomic, readonly ) UIView *promptView;
  19. @end
  20. @implementation FLEXObjcRuntimeViewController
  21. #pragma mark - Setup, view events
  22. - (void)viewDidLoad {
  23. [super viewDidLoad];
  24. // Long press on navigation bar to initialize webkit legacy
  25. //
  26. // We call initializeWebKitLegacy automatically before you search
  27. // all bundles just to be safe (since touching some classes before
  28. // WebKit is initialized will initialize it on a thread other than
  29. // the main thread), but sometimes you can encounter this crash
  30. // without searching through all bundles, of course.
  31. [self.navigationController.navigationBar addGestureRecognizer:[
  32. [UILongPressGestureRecognizer alloc]
  33. initWithTarget:[FLEXRuntimeClient class]
  34. action:@selector(initializeWebKitLegacy)
  35. ]
  36. ];
  37. // Search bar stuff, must be first because this creates self.searchController
  38. self.showsSearchBar = YES;
  39. self.showSearchBarInitially = YES;
  40. // Using pinSearchBar on this screen causes a weird visual
  41. // thing on the next view controller that gets pushed.
  42. //
  43. // self.pinSearchBar = YES;
  44. self.searchController.searchBar.placeholder = @"UIKit*.UIView.-setFrame:";
  45. // Search controller stuff
  46. // key path controller automatically assigns itself as the delegate of the search bar
  47. // To avoid a retain cycle below, use local variables
  48. UISearchBar *searchBar = self.searchController.searchBar;
  49. FLEXKeyPathSearchController *keyPathController = [FLEXKeyPathSearchController delegate:self];
  50. _keyPathController = keyPathController;
  51. _keyPathController.toolbar = [FLEXRuntimeBrowserToolbar toolbarWithHandler:^(NSString *text, BOOL suggestion) {
  52. if (suggestion) {
  53. [keyPathController didSelectKeyPathOption:text];
  54. } else {
  55. [keyPathController didPressButton:text insertInto:searchBar];
  56. }
  57. } suggestions:keyPathController.suggestions];
  58. }
  59. - (void)viewWillAppear:(BOOL)animated {
  60. [super viewWillAppear:animated];
  61. [self.tableView deselectRowAtIndexPath:self.tableView.indexPathForSelectedRow animated:YES];
  62. }
  63. - (void)viewDidAppear:(BOOL)animated {
  64. [super viewDidAppear:animated];
  65. dispatch_async(dispatch_get_main_queue(), ^{
  66. // This doesn't work unless it's wrapped in this dispatch_async call
  67. [self.searchController.searchBar becomeFirstResponder];
  68. });
  69. }
  70. #pragma mark Delegate stuff
  71. - (void)didSelectImagePath:(NSString *)path shortName:(NSString *)shortName {
  72. [FLEXAlert makeAlert:^(FLEXAlert *make) {
  73. make.title(shortName);
  74. make.message(@"No NSBundle associated with this path:\n\n");
  75. make.message(path);
  76. make.button(@"Copy Path").handler(^(NSArray<NSString *> *strings) {
  77. #if !TARGET_OS_TV
  78. UIPasteboard.generalPasteboard.string = path;
  79. #endif
  80. });
  81. make.button(@"Dismiss").cancelStyle();
  82. } showFrom:self];
  83. }
  84. - (void)didSelectBundle:(NSBundle *)bundle {
  85. NSParameterAssert(bundle);
  86. FLEXObjectExplorerViewController *explorer = [FLEXObjectExplorerFactory explorerViewControllerForObject:bundle];
  87. [self.navigationController pushViewController:explorer animated:YES];
  88. }
  89. - (void)didSelectClass:(Class)cls {
  90. NSParameterAssert(cls);
  91. FLEXObjectExplorerViewController *explorer = [FLEXObjectExplorerFactory explorerViewControllerForObject:cls];
  92. [self.navigationController pushViewController:explorer animated:YES];
  93. }
  94. #pragma mark - FLEXGlobalsEntry
  95. + (NSString *)globalsEntryTitle:(FLEXGlobalsRow)row {
  96. return @"📚 Runtime Browser";
  97. }
  98. + (UIViewController *)globalsEntryViewController:(FLEXGlobalsRow)row {
  99. UIViewController *controller = [self new];
  100. controller.title = [self globalsEntryTitle:row];
  101. return controller;
  102. }
  103. @end