FLEXArgumentInputStringView.m 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. //
  2. // FLEXArgumentInputStringView.m
  3. // Flipboard
  4. //
  5. // Created by Ryan Olson on 6/28/14.
  6. // Copyright (c) 2020 FLEX Team. All rights reserved.
  7. //
  8. #import "FLEXArgumentInputStringView.h"
  9. #import "FLEXRuntimeUtility.h"
  10. @implementation FLEXArgumentInputStringView
  11. - (instancetype)initWithArgumentTypeEncoding:(const char *)typeEncoding {
  12. self = [super initWithArgumentTypeEncoding:typeEncoding];
  13. if (self) {
  14. FLEXTypeEncoding type = typeEncoding[0];
  15. if (type == FLEXTypeEncodingConst) {
  16. // A crash here would mean an invalid type encoding string
  17. type = typeEncoding[1];
  18. }
  19. // Selectors don't need a multi-line text box
  20. if (type == FLEXTypeEncodingSelector) {
  21. self.targetSize = FLEXArgumentInputViewSizeSmall;
  22. } else {
  23. self.targetSize = FLEXArgumentInputViewSizeLarge;
  24. }
  25. }
  26. return self;
  27. }
  28. - (void)setInputValue:(id)inputValue {
  29. if ([inputValue isKindOfClass:[NSString class]]) {
  30. self.inputTextView.text = inputValue;
  31. } else if ([inputValue isKindOfClass:[NSValue class]]) {
  32. NSValue *value = (id)inputValue;
  33. NSParameterAssert(strlen(value.objCType) == 1);
  34. // C-String or SEL from NSValue
  35. FLEXTypeEncoding type = value.objCType[0];
  36. if (type == FLEXTypeEncodingConst) {
  37. // A crash here would mean an invalid type encoding string
  38. type = value.objCType[1];
  39. }
  40. if (type == FLEXTypeEncodingCString) {
  41. self.inputTextView.text = @((const char *)value.pointerValue);
  42. } else if (type == FLEXTypeEncodingSelector) {
  43. self.inputTextView.text = NSStringFromSelector((SEL)value.pointerValue);
  44. }
  45. }
  46. }
  47. - (id)inputValue {
  48. NSString *text = self.inputTextView.text;
  49. // Interpret empty string as nil. We loose the ability to set empty string as a string value,
  50. // but we accept that tradeoff in exchange for not having to type quotes for every string.
  51. if (!text.length) {
  52. return nil;
  53. }
  54. // Case: C-strings and SELs
  55. if (self.typeEncoding.length <= 2) {
  56. FLEXTypeEncoding type = [self.typeEncoding characterAtIndex:0];
  57. if (type == FLEXTypeEncodingConst) {
  58. // A crash here would mean an invalid type encoding string
  59. type = [self.typeEncoding characterAtIndex:1];
  60. }
  61. if (type == FLEXTypeEncodingCString || type == FLEXTypeEncodingSelector) {
  62. const char *encoding = self.typeEncoding.UTF8String;
  63. SEL selector = NSSelectorFromString(text);
  64. return [NSValue valueWithBytes:&selector objCType:encoding];
  65. }
  66. }
  67. // Case: NSStrings
  68. return self.inputTextView.text.copy;
  69. }
  70. // TODO: Support using object address for strings, as in the object arg view.
  71. + (BOOL)supportsObjCType:(const char *)type withCurrentValue:(id)value {
  72. NSParameterAssert(type);
  73. unsigned long len = strlen(type);
  74. BOOL isConst = type[0] == FLEXTypeEncodingConst;
  75. NSInteger i = isConst ? 1 : 0;
  76. BOOL typeIsString = strcmp(type, FLEXEncodeClass(NSString)) == 0;
  77. BOOL typeIsCString = len <= 2 && type[i] == FLEXTypeEncodingCString;
  78. BOOL typeIsSEL = len <= 2 && type[i] == FLEXTypeEncodingSelector;
  79. BOOL valueIsString = [value isKindOfClass:[NSString class]];
  80. BOOL typeIsPrimitiveString = typeIsSEL || typeIsCString;
  81. BOOL typeIsSupported = typeIsString || typeIsCString || typeIsSEL;
  82. BOOL valueIsNSValueWithCorrectType = NO;
  83. if ([value isKindOfClass:[NSValue class]]) {
  84. NSValue *v = (id)value;
  85. len = strlen(v.objCType);
  86. if (len == 1) {
  87. FLEXTypeEncoding type = v.objCType[i];
  88. if (type == FLEXTypeEncodingCString && typeIsCString) {
  89. valueIsNSValueWithCorrectType = YES;
  90. } else if (type == FLEXTypeEncodingSelector && typeIsSEL) {
  91. valueIsNSValueWithCorrectType = YES;
  92. }
  93. }
  94. }
  95. if (!value && typeIsSupported) {
  96. return YES;
  97. }
  98. if (typeIsString && valueIsString) {
  99. return YES;
  100. }
  101. // Primitive strings can be input as NSStrings or NSValues
  102. if (typeIsPrimitiveString && (valueIsString || valueIsNSValueWithCorrectType)) {
  103. return YES;
  104. }
  105. return NO;
  106. }
  107. @end