Просмотр исходного кода

Add support for char * and SEL string arguments

Tanner Bennett лет назад: 6
Родитель
Сommit
613a886604

+ 90 - 8
Classes/Editing/ArgumentInputViews/FLEXArgumentInputStringView.m

@@ -15,7 +15,18 @@
 {
     self = [super initWithArgumentTypeEncoding:typeEncoding];
     if (self) {
-        self.targetSize = FLEXArgumentInputViewSizeLarge;
+        FLEXTypeEncoding type = typeEncoding[0];
+        if (type == FLEXTypeEncodingConst) {
+            // A crash here would mean an invalid type encoding string
+            type = typeEncoding[1];
+        }
+
+        // Selectors don't need a multi-line text box
+        if (type == FLEXTypeEncodingSelector) {
+            self.targetSize = FLEXArgumentInputViewSizeSmall;
+        } else {
+            self.targetSize = FLEXArgumentInputViewSizeLarge;
+        }
     }
     return self;
 }
@@ -24,28 +35,99 @@
 {
     if ([inputValue isKindOfClass:[NSString class]]) {
         self.inputTextView.text = inputValue;
-    }
+    } else if ([inputValue isKindOfClass:[NSValue class]]) {
+        NSValue *value = (id)inputValue;
+        NSParameterAssert(strlen(value.objCType) == 1);
+
+        // C-String or SEL from NSValue
+        FLEXTypeEncoding type = value.objCType[0];
+        if (type == FLEXTypeEncodingConst) {
+            // A crash here would mean an invalid type encoding string
+            type = value.objCType[1];
+        }
 
-    // TODO: support NSValue coontaining char *
+        if (type == FLEXTypeEncodingCString) {
+            self.inputTextView.text = @((const char *)value.pointerValue);
+        } else if (type == FLEXTypeEncodingSelector) {
+            self.inputTextView.text = NSStringFromSelector((SEL)value.pointerValue);
+        }
+    }
 }
 
 - (id)inputValue
 {
+    NSString *text = self.inputTextView.text;
     // Interpret empty string as nil. We loose the ability to set empty string as a string value,
     // but we accept that tradeoff in exchange for not having to type quotes for every string.
-    return self.inputTextView.text.length > 0 ? [self.inputTextView.text copy] : nil;
+    if (!text.length) {
+        return nil;
+    }
+
+    // Case: C-strings and SELs
+    if (self.typeEncoding.length <= 2) {
+        FLEXTypeEncoding type = [self.typeEncoding characterAtIndex:0];
+        if (type == FLEXTypeEncodingConst) {
+            // A crash here would mean an invalid type encoding string
+            type = [self.typeEncoding characterAtIndex:1];
+        }
+
+        if (type == FLEXTypeEncodingCString || type == FLEXTypeEncodingSelector) {
+            const char *encoding = self.typeEncoding.UTF8String;
+            SEL selector = NSSelectorFromString(text);
+            return [NSValue valueWithBytes:&selector objCType:encoding];
+        }
+    }
+
+    // Case: NSStrings
+    return self.inputTextView.text.copy;
 }
 
 // TODO: Support using object address for strings, as in the object arg view.
 
-#pragma mark -
-
 + (BOOL)supportsObjCType:(const char *)type withCurrentValue:(id)value
 {
     NSParameterAssert(type);
+    unsigned long len = strlen(type);
+
+    BOOL isConst = type[0] == FLEXTypeEncodingConst;
+    NSInteger i = isConst ? 1 : 0;
+
     BOOL typeIsString = strcmp(type, FLEXEncodeClass(NSString)) == 0;
-    BOOL valueIsNilOrString = (!value || [value isKindOfClass:[NSString class]]);
-    return typeIsString && valueIsNilOrString;
+    BOOL typeIsCString = len <= 2 && type[i] == FLEXTypeEncodingCString;
+    BOOL typeIsSEL = len <= 2 && type[i] == FLEXTypeEncodingSelector;
+    BOOL valueIsString = [value isKindOfClass:[NSString class]];
+
+    BOOL typeIsPrimitiveString = typeIsSEL || typeIsCString;
+    BOOL typeIsSupported = typeIsString || typeIsCString || typeIsSEL;
+
+    BOOL valueIsNSValueWithCorrectType = NO;
+    if ([value isKindOfClass:[NSValue class]]) {
+        NSValue *v = (id)value;
+        len = strlen(v.objCType);
+        if (len == 1) {
+            FLEXTypeEncoding type = v.objCType[i];
+            if (type == FLEXTypeEncodingCString && typeIsCString) {
+                valueIsNSValueWithCorrectType = YES;
+            } else if (type == FLEXTypeEncodingSelector && typeIsSEL) {
+                valueIsNSValueWithCorrectType = YES;
+            }
+        }
+    }
+
+    if (!value && typeIsSupported) {
+        return YES;
+    }
+
+    if (typeIsString && valueIsString) {
+        return YES;
+    }
+
+    // Primitive strings can be input as NSStrings or NSValues
+    if (typeIsPrimitiveString && (valueIsString || valueIsNSValueWithCorrectType)) {
+        return YES;
+    }
+
+    return NO;
 }
 
 @end

+ 2 - 4
Classes/Editing/ArgumentInputViews/FLEXArgumentInputTextView.m

@@ -111,12 +111,10 @@
     [super layoutSubviews];
     
     self.inputTextView.frame = CGRectMake(0, self.topInputFieldVerticalLayoutGuide, self.bounds.size.width, [self inputTextViewHeight]);
-    // Placeholder label is positioned by insetting origin,
-    // which is the line fragment padding for X and 0 for Y,
+    // Placeholder label is positioned by insetting then origin
     // by the content inset then the text container inset
-    CGFloat leading = self.inputTextView.textContainer.lineFragmentPadding;
     CGSize s = self.inputTextView.frame.size;
-    self.placeholderLabel.frame = CGRectMake(leading, 0, s.width, s.height);
+    self.placeholderLabel.frame = CGRectMake(0, 0, s.width, s.height);
     self.placeholderLabel.frame = UIEdgeInsetsInsetRect(
         UIEdgeInsetsInsetRect(self.placeholderLabel.frame, self.inputTextView.contentInset),
         self.inputTextView.textContainerInset

+ 3 - 0
Classes/Editing/ArgumentInputViews/FLEXArgumentInputView.h

@@ -9,8 +9,11 @@
 #import <UIKit/UIKit.h>
 
 typedef NS_ENUM(NSUInteger, FLEXArgumentInputViewSize) {
+    /// 2 lines, medium-sized
     FLEXArgumentInputViewSizeDefault = 0,
+    /// One line
     FLEXArgumentInputViewSizeSmall,
+    /// Several lines
     FLEXArgumentInputViewSizeLarge
 };