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
111 lines
3.9 KiB
//
|
|
// FLEXMethodCallingViewController.m
|
|
// Flipboard
|
|
//
|
|
// Created by Ryan Olson on 5/23/14.
|
|
// Copyright (c) 2014 Flipboard. All rights reserved.
|
|
//
|
|
|
|
#import "FLEXMethodCallingViewController.h"
|
|
#import "FLEXRuntimeUtility.h"
|
|
#import "FLEXFieldEditorView.h"
|
|
#import "FLEXObjectExplorerFactory.h"
|
|
#import "FLEXObjectExplorerViewController.h"
|
|
#import "FLEXArgumentInputView.h"
|
|
#import "FLEXArgumentInputViewFactory.h"
|
|
|
|
@interface FLEXMethodCallingViewController ()
|
|
|
|
@property (nonatomic, assign) Method method;
|
|
@property (nonatomic, assign) FLEXTypeEncoding *returnType;
|
|
|
|
@end
|
|
|
|
@implementation FLEXMethodCallingViewController
|
|
|
|
- (id)initWithTarget:(id)target method:(Method)method
|
|
{
|
|
self = [super initWithTarget:target];
|
|
if (self) {
|
|
self.method = method;
|
|
self.returnType = [FLEXRuntimeUtility returnTypeForMethod:method];
|
|
self.title = [self isClassMethod] ? @"Class Method" : @"Method";;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)viewDidLoad
|
|
{
|
|
[super viewDidLoad];
|
|
|
|
NSString *returnType = @((const char *)self.returnType);
|
|
NSString *methodDescription = [FLEXRuntimeUtility prettyNameForMethod:self.method isClassMethod:[self isClassMethod]];
|
|
NSString *format = @"Signature:\n%@\n\nReturn Type:\n%@";
|
|
NSString *info = [NSString stringWithFormat:format, methodDescription, returnType];
|
|
self.fieldEditorView.fieldDescription = info;
|
|
|
|
NSArray<NSString *> *methodComponents = [FLEXRuntimeUtility prettyArgumentComponentsForMethod:self.method];
|
|
NSMutableArray<FLEXArgumentInputView *> *argumentInputViews = [NSMutableArray array];
|
|
unsigned int argumentIndex = kFLEXNumberOfImplicitArgs;
|
|
for (NSString *methodComponent in methodComponents) {
|
|
char *argumentTypeEncoding = method_copyArgumentType(self.method, argumentIndex);
|
|
FLEXArgumentInputView *inputView = [FLEXArgumentInputViewFactory argumentInputViewForTypeEncoding:argumentTypeEncoding];
|
|
free(argumentTypeEncoding);
|
|
|
|
inputView.backgroundColor = self.view.backgroundColor;
|
|
inputView.title = methodComponent;
|
|
[argumentInputViews addObject:inputView];
|
|
argumentIndex++;
|
|
}
|
|
self.fieldEditorView.argumentInputViews = argumentInputViews;
|
|
}
|
|
|
|
- (void)dealloc
|
|
{
|
|
free(self.returnType);
|
|
self.returnType = NULL;
|
|
}
|
|
|
|
- (BOOL)isClassMethod
|
|
{
|
|
return self.target && self.target == [self.target class];
|
|
}
|
|
|
|
- (NSString *)titleForActionButton
|
|
{
|
|
return @"Call";
|
|
}
|
|
|
|
- (void)actionButtonPressed:(id)sender
|
|
{
|
|
[super actionButtonPressed:sender];
|
|
|
|
NSMutableArray *arguments = [NSMutableArray array];
|
|
for (FLEXArgumentInputView *inputView in self.fieldEditorView.argumentInputViews) {
|
|
id argumentValue = inputView.inputValue;
|
|
if (!argumentValue) {
|
|
// Use NSNulls as placeholders in the array. They will be interpreted as nil arguments.
|
|
argumentValue = [NSNull null];
|
|
}
|
|
[arguments addObject:argumentValue];
|
|
}
|
|
|
|
NSError *error = nil;
|
|
id returnedObject = [FLEXRuntimeUtility performSelector:method_getName(self.method) onObject:self.target withArguments:arguments error:&error];
|
|
|
|
if (error) {
|
|
NSString *title = @"Method Call Failed";
|
|
NSString *message = [error localizedDescription];
|
|
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
|
|
[alert show];
|
|
} else if (returnedObject) {
|
|
// For non-nil (or void) return types, push an explorer view controller to display the returned object
|
|
returnedObject = [FLEXRuntimeUtility potentiallyUnwrapBoxedPointer:returnedObject type:self.returnType];
|
|
FLEXObjectExplorerViewController *explorerViewController = [FLEXObjectExplorerFactory explorerViewControllerForObject:returnedObject];
|
|
[self.navigationController pushViewController:explorerViewController animated:YES];
|
|
} else {
|
|
[self exploreObjectOrPopViewController:returnedObject];
|
|
}
|
|
}
|
|
|
|
@end
|