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.

101 lines
3.9 KiB

  1. //
  2. // FLEXPropertyEditorViewController.m
  3. // Flipboard
  4. //
  5. // Created by Ryan Olson on 5/20/14.
  6. // Copyright (c) 2014 Flipboard. All rights reserved.
  7. //
  8. #import "FLEXPropertyEditorViewController.h"
  9. #import "FLEXRuntimeUtility.h"
  10. #import "FLEXFieldEditorView.h"
  11. #import "FLEXArgumentInputView.h"
  12. #import "FLEXArgumentInputViewFactory.h"
  13. #import "FLEXArgumentInputSwitchView.h"
  14. @interface FLEXPropertyEditorViewController () <FLEXArgumentInputViewDelegate>
  15. @property (nonatomic, assign) objc_property_t property;
  16. @end
  17. @implementation FLEXPropertyEditorViewController
  18. - (id)initWithTarget:(id)target property:(objc_property_t)property
  19. {
  20. self = [super initWithTarget:target];
  21. if (self) {
  22. self.property = property;
  23. self.title = @"Property";
  24. }
  25. return self;
  26. }
  27. - (void)viewDidLoad
  28. {
  29. [super viewDidLoad];
  30. self.fieldEditorView.fieldDescription = [FLEXRuntimeUtility fullDescriptionForProperty:self.property];
  31. id currentValue = [FLEXRuntimeUtility valueForProperty:self.property onObject:self.target];
  32. self.setterButton.enabled = [[self class] canEditProperty:self.property currentValue:currentValue];
  33. const char *typeEncoding = [[FLEXRuntimeUtility typeEncodingForProperty:self.property] UTF8String];
  34. FLEXArgumentInputView *inputView = [FLEXArgumentInputViewFactory argumentInputViewForTypeEncoding:typeEncoding];
  35. inputView.backgroundColor = self.view.backgroundColor;
  36. inputView.inputValue = [FLEXRuntimeUtility valueForProperty:self.property onObject:self.target];
  37. inputView.delegate = self;
  38. self.fieldEditorView.argumentInputViews = @[inputView];
  39. // Don't show a "set" button for switches - just call the setter immediately after the switch toggles.
  40. if ([inputView isKindOfClass:[FLEXArgumentInputSwitchView class]]) {
  41. self.navigationItem.rightBarButtonItem = nil;
  42. }
  43. }
  44. - (void)actionButtonPressed:(id)sender
  45. {
  46. [super actionButtonPressed:sender];
  47. id userInputObject = self.firstInputView.inputValue;
  48. NSArray *arguments = userInputObject ? @[userInputObject] : nil;
  49. SEL setterSelector = [FLEXRuntimeUtility setterSelectorForProperty:self.property];
  50. NSError *error = nil;
  51. [FLEXRuntimeUtility performSelector:setterSelector onObject:self.target withArguments:arguments error:&error];
  52. if (error) {
  53. NSString *title = @"Property Setter Failed";
  54. NSString *message = [error localizedDescription];
  55. UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
  56. [alert show];
  57. self.firstInputView.inputValue = [FLEXRuntimeUtility valueForProperty:self.property onObject:self.target];
  58. } else {
  59. // If the setter was called without error, pop the view controller to indicate that and make the user's life easier.
  60. // Don't do this for simulated taps on the action button (i.e. from switch/BOOL editors). The experience is weird there.
  61. if (sender) {
  62. [self.navigationController popViewControllerAnimated:YES];
  63. }
  64. }
  65. }
  66. - (void)getterButtonPressed:(id)sender
  67. {
  68. [super getterButtonPressed:sender];
  69. id returnedObject = [FLEXRuntimeUtility valueForProperty:self.property onObject:self.target];
  70. [self exploreObjectOrPopViewController:returnedObject];
  71. }
  72. - (void)argumentInputViewValueDidChange:(FLEXArgumentInputView *)argumentInputView
  73. {
  74. if ([argumentInputView isKindOfClass:[FLEXArgumentInputSwitchView class]]) {
  75. [self actionButtonPressed:nil];
  76. }
  77. }
  78. + (BOOL)canEditProperty:(objc_property_t)property currentValue:(id)value
  79. {
  80. const char *typeEncoding = [[FLEXRuntimeUtility typeEncodingForProperty:property] UTF8String];
  81. BOOL canEditType = [FLEXArgumentInputViewFactory canEditFieldWithTypeEncoding:typeEncoding currentValue:value];
  82. BOOL isReadonly = [FLEXRuntimeUtility isReadonlyProperty:property];
  83. return canEditType && !isReadonly;
  84. }
  85. @end