如何为“oneOf”编写函数或宏...在变量函数中进行转换?

时间:2011-02-07 11:01:06

标签: iphone objective-c xcode ios macros

注意 - 使用可变参数, Phix 在下面提供了一个超级解决方案。但是,当它与整数一起使用时,它会给出编译器警告,因为你将它们转换为id,并且它不适用于例如浮点数。

问题 - 如何编写从列表中选择一个项目的设施?理想情况下,它会尽可能灵活地关于项目/对象的类型 /列表中的任何内容。

使用示例:

NSInteger openingMap = [utilities oneOf:1, 2, 3, 7, 8];

initialAngle =oneOf(1.25, 1.75, 1.95, 2.00, 2.01);

self.spaceShipNickName =oneOf(@"Blaster",@"Blitzen",@"Stardancer",@"Quantum");

self.chassisProperty = oneOf(titanium, neutronium, unavailablium);

[fireworksLayer paintStars:oneOf(blue,green,white) howMany:oneOf(20,25,50)];

[trump chooseDefaultSuite:oneOf(diamonds,hearts,clubs,spades)];

// normally have a few explosions, but, occasionally have a huge display...
explosionCount = oneOf( 2,2,2,3,4,1,28,3,3,3,70 );

请注意,一些示例是整数,一些枚举,一些NSStrings等。再次,如果一个工具可以处理不同类型,那将是最令人印象深刻的。 (而不是一个相关的组,比如...... oneOfIntegers,oneOfStrings,oneOfObject,等等。)

不用说,选择随机项目,只需使用...
= arcrandom()%number of of items

您可以使用 Objective C方法或类,c函数或某种宏系统,NSMutableArray的类别扩展,或者确实阻止 - 或其他任何内容。 它应该尽可能灵活,以便在典型的iOS或Mac项目的任何地方广泛使用......任何想法?

2 个答案:

答案 0 :(得分:2)

我把它作为NSArray上的一个类别(警告 - 此代码未经测试,可能有一个错误!)

@interface NSArray (one_of)
  - (id)anyObject;
@end

@implementation NSArray (one_of)

  - (id)anyObject {
    if (0 == [self count]) return nil;
    if (1 == [self count]) return [self objectAtIndex:0];

    return [self objectAtIndex:(arcrandom() % [self count])];
  }

@end

然后,使用它:

NSString *thingy = [[NSArray arrayWithObjects:@"1", @"2", @"3"] anyObject];

NB要处理数字(以及其他原生类型等),你必须使它们成为对象,即

NSInteger number = [[[NSArray arrayWithObjects:
                      [NSNumber numberWithInteger:1],
                      [NSNumber numberWithInteger:2],
                      [NSNumber numberWithInteger:3], nil] anyObject] intValue];

答案 1 :(得分:2)

#define NUMARGS(...)  (sizeof((id[]){__VA_ARGS__})/sizeof(id))
#define ONEOF(...)  (oneOf(NUMARGS(__VA_ARGS__), __VA_ARGS__))

id oneOf(int numargs, ...) {
    va_list ap; 
    va_start(ap,numargs);
    int i = arc4random() % numargs;
    id val = nil;
    do {
        val = va_arg(ap, id);
    } while (i--);
    va_end(ap);
    return val; 
}

用法:

NSLog(@"%@", ONEOF(@"Blaster",@"Blitzen",@"Stardancer",@"Quantum"));
NSLog(@"%d", ONEOF( 2,2,2,3,4,1,28,3,3,3,70 ));

请注意,两者都有效,但后者会抛出一些编译器警告。