FLEXRuntime+UIKitHelpers.m 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. //
  2. // FLEXRuntime+UIKitHelpers.m
  3. // FLEX
  4. //
  5. // Created by Tanner Bennett on 12/16/19.
  6. // Copyright © 2019 Flipboard. All rights reserved.
  7. //
  8. #import "FLEXRuntime+UIKitHelpers.h"
  9. #import "FLEXRuntimeUtility.h"
  10. #import "FLEXPropertyAttributes.h"
  11. #import "FLEXArgumentInputViewFactory.h"
  12. @implementation FLEXProperty (UIKitHelpers)
  13. - (BOOL)isEditable {
  14. if (self.attributes.isReadOnly) {
  15. return self.likelySetterExists;
  16. }
  17. const FLEXTypeEncoding *typeEncoding = self.attributes.typeEncoding.UTF8String;
  18. return [FLEXArgumentInputViewFactory canEditFieldWithTypeEncoding:typeEncoding currentValue:nil];
  19. }
  20. - (BOOL)isCallable {
  21. return YES;
  22. }
  23. - (UITableViewCellAccessoryType)suggestedAccessoryTypeWithTarget:(id)object {
  24. BOOL objectIsInstance = !object_isClass(object);
  25. // Decide whether to use object or [object class] to check for a potential value
  26. id targetForValueCheck = nil;
  27. if (objectIsInstance) {
  28. if (self.isClassProperty) {
  29. targetForValueCheck = [object class];
  30. } else {
  31. targetForValueCheck = object;
  32. }
  33. } else {
  34. if (self.isClassProperty) {
  35. targetForValueCheck = object;
  36. } else {
  37. // Instance property with a class object
  38. return UITableViewCellAccessoryNone;
  39. }
  40. }
  41. // We use .tag to store the cached value of .isEditable that is
  42. // initialized by FLEXObjectExplorer in -reloadMetada
  43. if ([self getPotentiallyUnboxedValue:targetForValueCheck]) {
  44. if (self.tag) {
  45. // Editable non-nil value, both
  46. return UITableViewCellAccessoryDetailDisclosureButton;
  47. } else {
  48. // Uneditable non-nil value, chevron only
  49. return UITableViewCellAccessoryDisclosureIndicator;
  50. }
  51. } else {
  52. if (self.tag) {
  53. // Editable nil value, just (i)
  54. return UITableViewCellAccessoryDetailButton;
  55. } else {
  56. // Non-editable nil value, neither
  57. return UITableViewCellAccessoryNone;
  58. }
  59. }
  60. }
  61. @end
  62. @implementation FLEXIvar (UIKitHelpers)
  63. - (BOOL)isEditable {
  64. const FLEXTypeEncoding *typeEncoding = self.typeEncoding.UTF8String;
  65. return [FLEXArgumentInputViewFactory canEditFieldWithTypeEncoding:typeEncoding currentValue:nil];
  66. }
  67. - (BOOL)isCallable {
  68. return NO;
  69. }
  70. - (UITableViewCellAccessoryType)suggestedAccessoryTypeWithTarget:(id)object {
  71. if (object_isClass(object)) {
  72. return UITableViewCellAccessoryNone;
  73. }
  74. // Could use .isEditable here, but we use .tag for speed since it is cached
  75. if ([self getPotentiallyUnboxedValue:object]) {
  76. if (self.tag) {
  77. // Editable non-nil value, both
  78. return UITableViewCellAccessoryDetailDisclosureButton;
  79. } else {
  80. // Uneditable non-nil value, chevron only
  81. return UITableViewCellAccessoryDisclosureIndicator;
  82. }
  83. } else {
  84. if (self.tag) {
  85. // Editable nil value, just (i)
  86. return UITableViewCellAccessoryDetailButton;
  87. } else {
  88. // Non-editable nil value, neither
  89. return UITableViewCellAccessoryNone;
  90. }
  91. }
  92. }
  93. @end
  94. @implementation FLEXMethodBase (UIKitHelpers)
  95. - (BOOL)isEditable {
  96. return NO;
  97. }
  98. - (BOOL)isCallable {
  99. return NO;
  100. }
  101. - (UITableViewCellAccessoryType)suggestedAccessoryTypeWithTarget:(id)object {
  102. // We shouldn't be using any FLEXMethodBase objects for this
  103. @throw NSInternalInconsistencyException;
  104. return UITableViewCellAccessoryNone;
  105. }
  106. @end
  107. @implementation FLEXMethod (UIKitHelpers)
  108. - (BOOL)isCallable {
  109. return self.signature != nil;
  110. }
  111. - (UITableViewCellAccessoryType)suggestedAccessoryTypeWithTarget:(id)object {
  112. if (self.isInstanceMethod) {
  113. if (object_isClass(object)) {
  114. // Instance method from class, can't call
  115. return UITableViewCellAccessoryNone;
  116. } else {
  117. // Instance method from instance, can call
  118. return UITableViewCellAccessoryDisclosureIndicator;
  119. }
  120. } else {
  121. return UITableViewCellAccessoryDisclosureIndicator;
  122. }
  123. }
  124. @end