FLEXArgumentInputStringView.m 4.2 KB

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