将CGFloats数组传递给方法

时间:2014-01-03 22:35:48

标签: ios variables methods

我仍然关注Obj C中的基本数据类型,所以这个真的在测试我。我已经查看了十几个或更多相关问题,仍然无法弄明白。

我在UIView子类中存在硬编码(基于我在某处找到的示例代码),因此:

CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();
CGFloat gradientColours[16] = {
    0.0f, 0.8f, 0.0f, 1.0f, // green
    1.0f, 1.0f, 0.0f, 1.0f, // yellow
    0.9f, 0.0f, 0.0f, 1.0f  // red
};
CGFloat gradientLocations[] = { 0.0, 0.5, 1.0 };
CGGradientRef gradient = CGGradientCreateWithColorComponents(colourSpace, gradientColours, gradientLocations, 3);

工作正常,但每个实例都会使用相同的渐变,所以我想添加一个方法来设置渐变。

我希望能够像

这样进行简单的调用
[myView1 setGradient:{
    0.0f, 0.8f, 0.0f, 1.0f, // green
    1.0f, 1.0f, 0.0f, 1.0f, // yellow
    0.9f, 0.0f, 0.0f, 1.0f  // red
    withLocations:{ 0.0, 0.5, 1.0 }];

我不能为我的生活弄清楚如何编写方法签名以接受这两个数组的方式,它们可以在CGGradientCreateWithColorComponents构造函数中成功使用。

任何帮助都非常感激。

2 个答案:

答案 0 :(得分:4)

 - (void) setGradient:(CGFloat*)gradientArray withArrayLength:(int)lengthOfArray {
      // do stuff here
 }

然后你可以调用这样的方法:

 CGFloat someArray[16] = { ... };
 [someObject setGradient:someArray withArrayLength:16];

编辑:Rob提醒我在这种情况下需要包含数组长度的参数。

答案 1 :(得分:2)

您可以使用NSArrayNSNumber字面语法来获取类似内容。以下是您的称呼方式:

[self setGradientColorComponents:@[
    @0.0f, @0.8f, @0.0f, @1.0f, // green
    @1.0f, @1.0f, @0.0f, @1.0f, // yellow
    @0.9f, @0.0f, @0.0f, @1.0f  // red
] withLocations:@[
    @0.0f, @0.5f, @1.0f
]];

以下是您如何实施它:

- (void)setGradientColorComponents:(NSArray *)components withLocations:(NSArray *)locations {
    NSUInteger count = components.count;
    CGFloat componentFloats[count];
    for (NSUInteger i = 0; i < count; ++i) {
        componentFloats[i] = [components[i] floatValue];
    }

    count = locations.count;
    CGFloat locationFloats[count];
    for (NSUInteger i = 0; i < count; ++i) {
        locationFloats[i] = [locations[i] floatValue];
    }

    CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
    CGGradientRef gradient = CGGradientCreateWithColorComponents(rgb, componentFloats, locationFloats, count);
    CGColorSpaceRelease(rgb);

    // do whatever with gradient

    CGGradientRelease(gradient);
}

另一方面,您可以使用可变参数函数。由于可变参数函数只能有一个可变参数列表,因此必须将这些位置与颜色组件混合。你还必须以某种方式标记列表的结尾。以下是您的称呼方式:

[self setGradient:
    0.0, 0.0, 0.8, 0.0, 1.0, // location 0.0, color green
    0.5, 1.0, 1.0, 0.0, 1.0, // location 0.5, color yellow
    1.0, 0.9, 0.0, 0.0, 1.0, // location 1.0, color red
    -1.0
];

这更危险,因为您需要确保只将双打传递给该函数,并且由您决定是否在列表末尾传递-1.0哨兵。我建议坚持使用我的第一个解决方案(使用NSArrayNSNumber文字)。也就是说,这是你实现可变方案的方法:

- (void)setGradient:(CGFloat)location0, ... {
    size_t count = 0;
    va_list ap;
    va_start(ap, location0);
    // Note that when you pass a float as a variadic argument, the compiler promotes it to double.
    double f = location0;
    while (f >= 0.0 && f <= 1.0) {
        ++count;
        f = va_arg(ap, double);
    }
    va_end(ap);
    NSAssert(count % 5 == 0, @"number of arguments is %lu which is not a multiple of 5", (unsigned long)count);

    count /= 5;
    CGFloat locations[count];
    CGFloat components[4 * count];
    va_start(ap, location0);
    f = location0;
    for (size_t i = 0; i < count; ++i) {
        locations[i] = (CGFloat)f; f = va_arg(ap, double);
        components[i * 4 + 0] = (CGFloat)f; f = va_arg(ap, double);
        components[i * 4 + 1] = (CGFloat)f; f = va_arg(ap, double);
        components[i * 4 + 2] = (CGFloat)f; f = va_arg(ap, double);
        components[i * 4 + 3] = (CGFloat)f; f = va_arg(ap, double);
    }
    va_end(ap);

    CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
    CGGradientRef gradient = CGGradientCreateWithColorComponents(rgb, components, locations, count);
    CGColorSpaceRelease(rgb);

    // do whatever with gradient

    CGGradientRelease(gradient);
}