Objective C 中接受基元的可变参数函数

Variadic function in Objective C that accepts primitives

提问人:griotspeak 提问时间:11/29/2010 最后编辑:Alex Graygriotspeak 更新时间:10/16/2012 访问量:1555

问:

现在,我有这个:

// .h
- (NSArray *)createNumberArrayWithInts:(NSInteger)firstArg, ...
    NS_REQUIRES_NIL_TERMINATION;

// .m
- (NSArray *)newNumberArrayWithInts:(NSInteger)firstArg, ... {
    NSMutableArray *lCreatedArray = [NSMutableArray alloc];

    va_list args;
    va_start(args, firstArg);
    for (NSInteger arg = firstArg; arg != nil; arg = va_arg(args, NSInteger)) {
        NSNumber *lTempNumberObject = [[NSNumber alloc] initWithInteger:arg];
        [lCreatedArray addObject:lTempNumberObject];
        [lTempNumberObject release];

    }
    va_end(args);

    NSArray *lImmutableArray = [[NSArray alloc] initWithArray:lCreatedArray];
    [lCreatedArray release];

    return lImmutableArray;
}

但是与 nil 的比较是不正确的,因为 int 不是对象。使用 NSNumbers 会破坏我的目的,因为我试图不在此方法之外分配对象。

该怎么办?

objective-c 语法 常量 原始类型 variadic-functions

评论


答:

4赞 Jason Coco 11/29/2010 #1

这个问题在 C 中也存在。如果你使用这样的整数,你就不能使用哨兵(正如你所发现的)。大多数人所做的是将第一个参数定义为大小。因此,您的原型可能如下所示:

- (NSArray *)createNumberArrayWithInts:(NSUInteger)length, ...

这种设计的明显问题是编译器无法检查它。如果你在大小上犯了错误,你可能会遇到麻烦,但这与你在 C 中遇到的问题完全相同,即使你传递了一个 ints 数组或类似的东西。由调用方确保大小正确。

另一种解决方案是使用非法 int 作为哨兵。所以,选择MAX_INT之类的东西。当您发现时,请停止阅读列表。然而,同样,你不能真正让编译器对此发出警告......

评论

1赞 JeremyP 11/30/2010
我认为,如果整数的类型是 ,则最佳哨兵值可能是 应该是可表示为 的最大可能值。NSIntegerNSNotFoundNSInteger
1赞 Jason Coco 11/30/2010
@JeremyP:实际上,既然他使用的是 NSInteger,那么他可能应该使用 NSIntegerMax。NSNotFound 实际上被定义为 NSIntegerMax,但 IMO 使用 NSIntegerMax 更合适。不过,老实说,我认为将整数数作为第一个必需参数是解决这个问题的最佳解决方案。
0赞 griotspeak 11/30/2010
在过去的 2 小时内,我来回讨论哪个最好。我现在正在使用 NSNotFound 方法,但为什么您更喜欢将长度作为必需的第一个参数?(我只选择了NSNotFound以提高可读性)
0赞 Jason Coco 11/30/2010
@griotspeak:长度是 C 语言中完成的方式,而且它不会从池中删除潜在的整数。您可能还想创建自己的更具可读性的哨兵常量,并将其定义为 NSIntegerMax,而不是重载 NSNotFound,这实际上没有意义作为哨兵名称。
3赞 Alex Gray 10/16/2012 #2

好吧,对于那些对原始人感到困惑的人来说,VA_ARGS......这是给大家的答案。在这里,我展示了一个类别,它采用可变长度的“列表”(s),并将它们应用于图层。CALayerCAConstraintAttribute

@interface CALayer (VariadicConstraints)
- (void)addConstraintsRelSuper:(CAConstraintAttribute)first,...; 
/* REQUIRES NSNotFound termination */
@end

@implementation CALayer (VariadicConstraints)
- (void)addConstraintsRelSuper:(CAConstraintAttribute)first,...{ /* REQUIRES NSNotFound termination */
   va_list args;   va_start(args, first);
   for (NSUInteger arg = first;  arg != NSNotFound;
                   arg = va_arg( args, NSUInteger))
   { [self addConstraint:CAConstRelSuper(arg)]; }
   va_end(args);
}
@end

现在,添加层约束被简化为...

[layer addConstraintsRelSuper:kCAConstraintMaxX, kCAConstraintHeight, NSNotFound];

NSLOG layer.constraints➞ “[MaxX = 超层。MaxX]“, “[高度 = 超层。高度]”

...从以前有数百个字符。

为了完整起见..这是我的宏...CAConstRelSuper

#define CAConstRelSuper(attr) [CAConstraint constraintWithAttribute: \
attr relativeTo:@"superlayer" attribute:attr]