You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

111 lines
3.9 KiB

  1. //
  2. // FLEXMethodCallingViewController.m
  3. // Flipboard
  4. //
  5. // Created by Ryan Olson on 5/23/14.
  6. // Copyright (c) 2014 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. @interface FLEXMethodCallingViewController ()
  16. @property (nonatomic, assign) Method method;
  17. @property (nonatomic, assign) FLEXTypeEncoding *returnType;
  18. @end
  19. @implementation FLEXMethodCallingViewController
  20. - (id)initWithTarget:(id)target method:(Method)method
  21. {
  22. self = [super initWithTarget:target];
  23. if (self) {
  24. self.method = method;
  25. self.returnType = [FLEXRuntimeUtility returnTypeForMethod:method];
  26. self.title = [self isClassMethod] ? @"Class Method" : @"Method";;
  27. }
  28. return self;
  29. }
  30. - (void)viewDidLoad
  31. {
  32. [super viewDidLoad];
  33. NSString *returnType = @((const char *)self.returnType);
  34. NSString *methodDescription = [FLEXRuntimeUtility prettyNameForMethod:self.method isClassMethod:[self isClassMethod]];
  35. NSString *format = @"Signature:\n%@\n\nReturn Type:\n%@";
  36. NSString *info = [NSString stringWithFormat:format, methodDescription, returnType];
  37. self.fieldEditorView.fieldDescription = info;
  38. NSArray<NSString *> *methodComponents = [FLEXRuntimeUtility prettyArgumentComponentsForMethod:self.method];
  39. NSMutableArray<FLEXArgumentInputView *> *argumentInputViews = [NSMutableArray array];
  40. unsigned int argumentIndex = kFLEXNumberOfImplicitArgs;
  41. for (NSString *methodComponent in methodComponents) {
  42. char *argumentTypeEncoding = method_copyArgumentType(self.method, argumentIndex);
  43. FLEXArgumentInputView *inputView = [FLEXArgumentInputViewFactory argumentInputViewForTypeEncoding:argumentTypeEncoding];
  44. free(argumentTypeEncoding);
  45. inputView.backgroundColor = self.view.backgroundColor;
  46. inputView.title = methodComponent;
  47. [argumentInputViews addObject:inputView];
  48. argumentIndex++;
  49. }
  50. self.fieldEditorView.argumentInputViews = argumentInputViews;
  51. }
  52. - (void)dealloc
  53. {
  54. free(self.returnType);
  55. self.returnType = NULL;
  56. }
  57. - (BOOL)isClassMethod
  58. {
  59. return self.target && self.target == [self.target class];
  60. }
  61. - (NSString *)titleForActionButton
  62. {
  63. return @"Call";
  64. }
  65. - (void)actionButtonPressed:(id)sender
  66. {
  67. [super actionButtonPressed:sender];
  68. NSMutableArray *arguments = [NSMutableArray array];
  69. for (FLEXArgumentInputView *inputView in self.fieldEditorView.argumentInputViews) {
  70. id argumentValue = inputView.inputValue;
  71. if (!argumentValue) {
  72. // Use NSNulls as placeholders in the array. They will be interpreted as nil arguments.
  73. argumentValue = [NSNull null];
  74. }
  75. [arguments addObject:argumentValue];
  76. }
  77. NSError *error = nil;
  78. id returnedObject = [FLEXRuntimeUtility performSelector:method_getName(self.method) onObject:self.target withArguments:arguments error:&error];
  79. if (error) {
  80. NSString *title = @"Method Call Failed";
  81. NSString *message = [error localizedDescription];
  82. UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
  83. [alert show];
  84. } else if (returnedObject) {
  85. // For non-nil (or void) return types, push an explorer view controller to display the returned object
  86. returnedObject = [FLEXRuntimeUtility potentiallyUnwrapBoxedPointer:returnedObject type:self.returnType];
  87. FLEXObjectExplorerViewController *explorerViewController = [FLEXObjectExplorerFactory explorerViewControllerForObject:returnedObject];
  88. [self.navigationController pushViewController:explorerViewController animated:YES];
  89. } else {
  90. [self exploreObjectOrPopViewController:returnedObject];
  91. }
  92. }
  93. @end