【问题标题】:@NotEmpty annotation in Objective C?目标C中的@NotEmpty注释?
【发布时间】:2020-05-13 12:35:35
【问题描述】:

是否有可能创建自定义注释来检查方法的参数是空数组还是空字符串? Java中的@NotEmpty之类的东西。我已经使用 _Nonnull 并使用 NSParameterAssert 检查参数,但我很好奇我们可以编写自定义注释吗? 谢谢。

【问题讨论】:

    标签: ios objective-c annotations


    【解决方案1】:

    您可以使用宏来定义内联函数。

    #define isNil(x) nil ==x
    

    【讨论】:

    • 我不能将它用作方法的参数类型。
    【解决方案2】:

    Objective-C 没有此类可自定义的注释,但其主要优势之一是其运行时的多功能性。

    因此,如果我们真的想要,我们可以使用包装类类型来实现它:

    @interface NotEmpty<Object> : NSProxy
    @property(readonly,copy) Object object;
    + (instancetype)notEmpty:(Object)object;
    - (instancetype)initWithObject:(Object)object;
    @end
    
    @implementation NotEmpty {
        id _object;
    }
    - (id)object {
        return _object;
    }
    + (instancetype)notEmpty:(id)object {
        return [[self alloc] initWithObject:object];
    }
    - (instancetype)initWithObject:(id)object {
        if ([object respondsToSelector:@selector(length)]) {
            NSParameterAssert([object length] != 0);
        } else {
            NSParameterAssert([object count] != 0);
        }
        _object = [object copy];
        return self;
    }
    - (NSMethodSignature *)methodSignatureForSelector:(SEL)selector {
        if (selector == @selector(object)) {
            return [NSMethodSignature signatureWithObjCTypes:"@:"];
        } else {
            return [_object methodSignatureForSelector:selector];
        }
    }
    - (void)forwardInvocation:(NSInvocation *)invocation {
        invocation.target = _object;
        [invocation invoke];
    }
    @end
    
    @interface SomeClass : NSObject
    @end
    
    @implementation SomeClass
    - (void)method:(NotEmpty<NSString*> *)nonEmptyString {
        // Call NSString methods, option 1
        unsigned long length1 = [(id)nonEmptyString length];
        // Call NSString methods, option 2
        unsigned long length2 = nonEmptyString.object.length; 
    
        // Note that just printing `nonEmptyString` (not nonEmptyString.object)
        // will print an opaque value. If this is a concern, then also forward
        // @selector(description) from -methodSignatureForSelector:.
        NSLog(@"Received: %@ (length1: %lu length2: %lu)", nonEmptyString.object, length1, length2);
    }
    @end
    
    int main() {
        SomeClass *sc = [SomeClass new];
        [sc method:[NotEmpty notEmpty:@"Not an empty string"]];
        // [sc method:[NotEmpty notEmpty:@""]]; // Raises error
    }
    

    请注意,这会导致一些小的性能损失。

    【讨论】:

      猜你喜欢
      • 2015-02-10
      • 2011-01-23
      • 1970-01-01
      • 2014-10-05
      • 2014-12-27
      • 1970-01-01
      • 1970-01-01
      • 2016-05-23
      • 1970-01-01
      相关资源
      最近更新 更多