从NSNumber获得CGFloat最常见和最正确的做法是什么?

时间:2014-01-20 10:19:05

标签: ios objective-c cocoa-touch

我的工作代码如下:

NSNumber *n = @42.42;
CGFloat cgf = 0; 
CFNumberRef cfn = CFBridgingRetain(n);
CFNumberGetValue(cfn, kCFNumberCGFloatType, &cgf);
CFRelease(cfn);

也可能

CGFloat cgf = (CGFLOAT_IS_DOUBLE) ? [n doubleValue] : [n floatValue];

但这对我来说更加丑陋。

在我看来应该有更好的API来做这样一个普通的事情。有吗?

3 个答案:

答案 0 :(得分:12)

在任何情况下都会得到正确的结果:

 NSNumber *n = @42.42;
 CGFloat cgf = [n doubleValue];

因为CGFloatfloatdouble


NSNumber没有CGFloatValue方法。你可以定义一个 使用免费桥接到CFNumberRef

@interface NSNumber (MyCGFloatValue)
-(CGFloat)myCGFloatValue;
@end

@implementation NSNumber (MyCGFloatValue)
-(CGFloat)myCGFloatValue{
    CGFloat result;
    CFNumberGetValue((__bridge CFNumberRef)(self), kCFNumberCGFloatType, &result);
    return result;
}
@end

或使用C11功能“通用选择”,其中编译器选择适当的选项 代码取决于CGFloat的类型:

@implementation NSNumber (MyCGFloatValue)
-(CGFloat)myCGFloatValue{
    CGFloat result;
    result = _Generic(result,
            double: [self doubleValue],
            float: [self floatValue]);
    return result;
}
@end

然后

NSNumber *n = @42.24;
CGFloat f = [n myCGFloatValue];

但我怀疑这是值得的麻烦。

答案 1 :(得分:4)

总是得到双倍价值。如果CGFloat只是你机器上的'浮动',那么双重会立即被截断,所以你不在乎。

答案 2 :(得分:1)

旧答案都是正确的。只是为了我的2美分,这是我的实施:

@implementation NSNumber (TypeConversion)

- (CGFloat)cgFloatValue
{
#if CGFLOAT_IS_DOUBLE
    return self.doubleValue;
#else
    return self.floatValue;
#endif
}

@end

这依赖于CGBase.h中针对Objective C的CGFLOAT_IS_DOUBLE的定义,或者针对Swift的CoreGraphics.h的定义:

// Don't write this code; it's already included in Foundation :)

#if defined(__LP64__) && __LP64__
# define CGFLOAT_TYPE double
# define CGFLOAT_IS_DOUBLE 1
# define CGFLOAT_MIN DBL_MIN
# define CGFLOAT_MAX DBL_MAX
#else
# define CGFLOAT_TYPE float
# define CGFLOAT_IS_DOUBLE 0
# define CGFLOAT_MIN FLT_MIN
# define CGFLOAT_MAX FLT_MAX
#endif

typedef CGFLOAT_TYPE CGFloat;
#define CGFLOAT_DEFINED 1

来自CoreGraphics.h