FLEXViewShortcuts.m 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. //
  2. // FLEXViewShortcuts.m
  3. // FLEX
  4. //
  5. // Created by Tanner Bennett on 12/11/19.
  6. // Copyright © 2020 FLEX Team. All rights reserved.
  7. //
  8. #import "FLEXViewShortcuts.h"
  9. #import "FLEXShortcut.h"
  10. #import "FLEXRuntimeUtility.h"
  11. #import "FLEXObjectExplorerFactory.h"
  12. #import "FLEXImagePreviewViewController.h"
  13. @interface FLEXViewShortcuts ()
  14. @property (nonatomic, readonly) UIView *view;
  15. @end
  16. @implementation FLEXViewShortcuts
  17. #pragma mark - Internal
  18. - (UIView *)view {
  19. return self.object;
  20. }
  21. + (UIViewController *)viewControllerForView:(UIView *)view {
  22. NSString *viewDelegate = @"viewDelegate";
  23. if ([view respondsToSelector:NSSelectorFromString(viewDelegate)]) {
  24. return [view valueForKey:viewDelegate];
  25. }
  26. return nil;
  27. }
  28. + (UIViewController *)viewControllerForAncestralView:(UIView *)view {
  29. NSString *_viewControllerForAncestor = @"_viewControllerForAncestor";
  30. if ([view respondsToSelector:NSSelectorFromString(_viewControllerForAncestor)]) {
  31. return [view valueForKey:_viewControllerForAncestor];
  32. }
  33. return nil;
  34. }
  35. + (UIViewController *)nearestViewControllerForView:(UIView *)view {
  36. return [self viewControllerForView:view] ?: [self viewControllerForAncestralView:view];
  37. }
  38. #pragma mark - Overrides
  39. + (instancetype)forObject:(UIView *)view {
  40. // In the past, FLEX would not hold a strong reference to something like this.
  41. // After using FLEX for so long, I am certain it is more useful to eagerly
  42. // reference something as useful as a view controller so that the reference
  43. // is not lost and swept out from under you before you can access it.
  44. //
  45. // The alternative here is to use a future in place of `controller` which would
  46. // dynamically grab a reference to the view controller. 99% of the time, however,
  47. // it is not all that useful. If you need it to refresh, you can simply go back
  48. // and go forward again and it will show if the view controller is nil or changed.
  49. UIViewController *controller = [FLEXViewShortcuts nearestViewControllerForView:view];
  50. return [self forObject:view additionalRows:@[
  51. [FLEXActionShortcut title:@"Nearest View Controller"
  52. subtitle:^NSString *(id view) {
  53. return [FLEXRuntimeUtility safeDescriptionForObject:controller];
  54. }
  55. viewer:^UIViewController *(id view) {
  56. return [FLEXObjectExplorerFactory explorerViewControllerForObject:controller];
  57. }
  58. accessoryType:^UITableViewCellAccessoryType(id view) {
  59. return controller ? UITableViewCellAccessoryDisclosureIndicator : UITableViewCellAccessoryNone;
  60. }
  61. ],
  62. [FLEXActionShortcut title:@"Preview Image" subtitle:^NSString *(UIView *view) {
  63. return !CGRectIsEmpty(view.bounds) ? @"" : @"Unavailable with empty bounds";
  64. }
  65. viewer:^UIViewController *(UIView *view) {
  66. return [FLEXImagePreviewViewController previewForView:view];
  67. }
  68. accessoryType:^UITableViewCellAccessoryType(UIView *view) {
  69. // Disable preview if bounds are CGRectZero
  70. return !CGRectIsEmpty(view.bounds) ? UITableViewCellAccessoryDisclosureIndicator : UITableViewCellAccessoryNone;
  71. }
  72. ]
  73. ]];
  74. }
  75. @end