FLEXMethodCallingViewController.m 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  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. @interface FLEXMethodCallingViewController ()
  15. @property (nonatomic, assign) Method method;
  16. @end
  17. @implementation FLEXMethodCallingViewController
  18. - (id)initWithTarget:(id)target method:(Method)method
  19. {
  20. self = [super initWithTarget:target];
  21. if (self) {
  22. self.method = method;
  23. self.title = [self isClassMethod] ? @"Class Method" : @"Method";
  24. }
  25. return self;
  26. }
  27. - (void)viewDidLoad
  28. {
  29. [super viewDidLoad];
  30. self.fieldEditorView.fieldDescription = [FLEXRuntimeUtility prettyNameForMethod:self.method isClassMethod:[self isClassMethod]];
  31. NSArray *methodComponents = [FLEXRuntimeUtility prettyArgumentComponentsForMethod:self.method];
  32. NSMutableArray *argumentInputViews = [NSMutableArray array];
  33. unsigned int argumentIndex = kFLEXNumberOfImplicitArgs;
  34. for (NSString *methodComponent in methodComponents) {
  35. FLEXArgumentInputView *inputView = [[FLEXArgumentInputView alloc] init];
  36. inputView.backgroundColor = self.view.backgroundColor;
  37. inputView.title = methodComponent;
  38. // Prepopulate the structs that we parse from strings with the default values.
  39. // This shows the intended formatting which would be less clear otherwise.
  40. char *argumentTypeEncoding = method_copyArgumentType(self.method, argumentIndex);
  41. NSValue *defaultValue = [[self class] defaultValueForEncoding:argumentTypeEncoding];
  42. if (defaultValue) {
  43. inputView.inputText = [FLEXRuntimeUtility editiableDescriptionForObject:defaultValue];
  44. }
  45. free(argumentTypeEncoding);
  46. [argumentInputViews addObject:inputView];
  47. argumentIndex++;
  48. }
  49. self.fieldEditorView.argumentInputViews = argumentInputViews;
  50. }
  51. - (BOOL)isClassMethod
  52. {
  53. return self.target && self.target == [self.target class];
  54. }
  55. - (NSString *)titleForActionButton
  56. {
  57. return @"Call";
  58. }
  59. - (void)actionButtonPressed:(id)sender
  60. {
  61. [super actionButtonPressed:sender];
  62. NSMutableArray *arguments = [NSMutableArray array];
  63. for (FLEXArgumentInputView *inputView in self.fieldEditorView.argumentInputViews) {
  64. NSString *argumentString = inputView.inputText;
  65. if (!argumentString) {
  66. // Use empty string as a placeholder in the array. It will be interpreted as nil.
  67. argumentString = @"";
  68. }
  69. [arguments addObject:argumentString];
  70. }
  71. id returnedObject = [FLEXRuntimeUtility performSelector:method_getName(self.method) onObject:self.target withArguments:arguments error:NULL];
  72. // For non-nil (or void) return types, push an explorer view controller to display the returned object
  73. if (returnedObject) {
  74. FLEXObjectExplorerViewController *explorerViewController = [FLEXObjectExplorerFactory explorerViewControllerForObject:returnedObject];
  75. [self.navigationController pushViewController:explorerViewController animated:YES];
  76. }
  77. }
  78. + (NSValue *)defaultValueForEncoding:(const char *)typeEncoding
  79. {
  80. NSValue *value = nil;
  81. if (strcmp(typeEncoding, @encode(CGRect)) == 0) {
  82. value = [NSValue valueWithCGRect:CGRectZero];
  83. } else if (strcmp(typeEncoding, @encode(CGSize)) == 0) {
  84. value = [NSValue valueWithCGPoint:CGPointZero];
  85. } else if (strcmp(typeEncoding, @encode(CGPoint)) == 0) {
  86. value = [NSValue valueWithCGSize:CGSizeZero];
  87. } else if (strcmp(typeEncoding, @encode(CGAffineTransform)) == 0) {
  88. value = [NSValue valueWithCGAffineTransform:CGAffineTransformIdentity];
  89. } else if (strcmp(typeEncoding, @encode(NSRange)) == 0) {
  90. value = [NSValue valueWithRange:NSMakeRange(0, 0)];
  91. } else if (strcmp(typeEncoding, @encode(UIEdgeInsets)) == 0) {
  92. value = [NSValue valueWithUIEdgeInsets:UIEdgeInsetsZero];
  93. } else if (strcmp(typeEncoding, @encode(UIOffset)) == 0) {
  94. value = [NSValue valueWithUIOffset:UIOffsetZero];
  95. }
  96. return value;
  97. }
  98. @end