FLEXMethodCallingViewController.m 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. //
  2. // FLEXMethodCallingViewController.m
  3. // Flipboard
  4. //
  5. // Created by Ryan Olson on 5/23/14.
  6. // Copyright (c) 2020 Flipboard. All rights reserved.
  7. //
  8. #import "FLEXMethodCallingViewController.h"
  9. #import "FLEXRuntimeUtility.h"
  10. #import "FLEXFieldEditorView.h"
  11. #import "FLEXObjectExplorerFactory.h"
  12. #import "FLEXObjectExplorerViewController.h"
  13. #import "FLEXArgumentInputView.h"
  14. #import "FLEXArgumentInputViewFactory.h"
  15. #import "FLEXUtility.h"
  16. @interface FLEXMethodCallingViewController ()
  17. @property (nonatomic) FLEXMethod *method;
  18. @end
  19. @implementation FLEXMethodCallingViewController
  20. + (instancetype)target:(id)target method:(FLEXMethod *)method {
  21. return [[self alloc] initWithTarget:target method:method];
  22. }
  23. - (id)initWithTarget:(id)target method:(FLEXMethod *)method {
  24. NSParameterAssert(method.isInstanceMethod == !object_isClass(target));
  25. self = [super initWithTarget:target];
  26. if (self) {
  27. self.method = method;
  28. self.title = method.isInstanceMethod ? @"Method: " : @"Class Method: ";
  29. self.title = [self.title stringByAppendingString:method.selectorString];
  30. }
  31. return self;
  32. }
  33. - (void)viewDidLoad {
  34. [super viewDidLoad];
  35. self.actionButton.title = @"Call";
  36. // Configure field editor view
  37. self.fieldEditorView.argumentInputViews = [self argumentInputViews];
  38. self.fieldEditorView.fieldDescription = [NSString stringWithFormat:
  39. @"Signature:\n%@\n\nReturn Type:\n%s",
  40. self.method.description, (char *)self.method.returnType
  41. ];
  42. }
  43. - (NSArray<FLEXArgumentInputView *> *)argumentInputViews {
  44. Method method = self.method.objc_method;
  45. NSArray *methodComponents = [FLEXRuntimeUtility prettyArgumentComponentsForMethod:method];
  46. NSMutableArray<FLEXArgumentInputView *> *argumentInputViews = [NSMutableArray new];
  47. unsigned int argumentIndex = kFLEXNumberOfImplicitArgs;
  48. for (NSString *methodComponent in methodComponents) {
  49. char *argumentTypeEncoding = method_copyArgumentType(method, argumentIndex);
  50. FLEXArgumentInputView *inputView = [FLEXArgumentInputViewFactory argumentInputViewForTypeEncoding:argumentTypeEncoding];
  51. free(argumentTypeEncoding);
  52. inputView.backgroundColor = self.view.backgroundColor;
  53. inputView.title = methodComponent;
  54. [argumentInputViews addObject:inputView];
  55. argumentIndex++;
  56. }
  57. return argumentInputViews;
  58. }
  59. - (void)actionButtonPressed:(id)sender {
  60. [super actionButtonPressed:sender];
  61. // Gather arguments
  62. NSMutableArray *arguments = [NSMutableArray new];
  63. for (FLEXArgumentInputView *inputView in self.fieldEditorView.argumentInputViews) {
  64. // Use NSNull as a nil placeholder; it will be interpreted as nil
  65. [arguments addObject:inputView.inputValue ?: NSNull.null];
  66. }
  67. // Call method
  68. NSError *error = nil;
  69. id returnValue = [FLEXRuntimeUtility
  70. performSelector:self.method.selector
  71. onObject:self.target
  72. withArguments:arguments
  73. error:&error
  74. ];
  75. // Display return value or error
  76. if (error) {
  77. [FLEXAlert showAlert:@"Method Call Failed" message:error.localizedDescription from:self];
  78. } else if (returnValue) {
  79. // For non-nil (or void) return types, push an explorer view controller to display the returned object
  80. returnValue = [FLEXRuntimeUtility potentiallyUnwrapBoxedPointer:returnValue type:self.method.returnType];
  81. FLEXObjectExplorerViewController *explorer = [FLEXObjectExplorerFactory explorerViewControllerForObject:returnValue];
  82. [self.navigationController pushViewController:explorer animated:YES];
  83. } else {
  84. [self exploreObjectOrPopViewController:returnValue];
  85. }
  86. }
  87. @end