What is most common and correct practice to get a CGFloat from an NSNumber?
This will get the correct result in any case:
NSNumber *n = @42.42;
CGFloat cgf = [n doubleValue];
because CGFloat
is either float
or double
.
NSNumber
does not have a CGFloatValue
method. You could define one
using the toll-free bridge to CFNumberRef
:
@interface NSNumber (MyCGFloatValue)
-(CGFloat)myCGFloatValue;
@end
@implementation NSNumber (MyCGFloatValue)
-(CGFloat)myCGFloatValue{
CGFloat result;
CFNumberGetValue((__bridge CFNumberRef)(self), kCFNumberCGFloatType, &result);
return result;
}
@end
or using the C11 feature "Generic selection", where the compiler chooses the appropriate
code depending on the type of CGFloat
:
@implementation NSNumber (MyCGFloatValue)
-(CGFloat)myCGFloatValue{
CGFloat result;
result = _Generic(result,
double: [self doubleValue],
float: [self floatValue]);
return result;
}
@end
And then
NSNumber *n = @42.24;
CGFloat f = [n myCGFloatValue];
but I doubt that it is worth the hassle.
Conversion between CGFloat and NSNumber without unnecessary promotion to Double
Update: One can cast a CGFloat
value to NSNumber
and back:
let c1 = CGFloat(12.3)
let num = c1 as NSNumber
let c2 = num as CGFloat
This preserves the precision of CGFloat
and works with Swift 2
and Swift 3.
(Previous answer – far too complicated): There are two solutions that I found. The first uses the toll-free bridging
between NSNumber
and CFNumber
(as in What is most common and correct practice to get a CGFloat from an NSNumber?
for Objective-C). It uses the fact that CFNumber
has a dedicated
conversion mode for CGFloat
values:
extension NSNumber {
// CGFloat -> NSNumber
class func numberWithCGFloat(var value: CGFloat) -> NSNumber {
return CFNumberCreate(nil , .CGFloatType, &value)
}
// NSNumber -> CGFloat
var cgFloatValue : CGFloat {
var value : CGFloat = 0
CFNumberGetValue(self, .CGFloatType, &value)
return value
}
}
That is simple and nice. The only drawback: I could not figure out
how to make the constructor an init
method instead of a class method
.
The second possible solution is a bit longer:
extension NSNumber {
// CGFloat -> NSNumber
private convenience init(doubleOrFloat d : Double) {
self.init(double : d)
}
private convenience init(doubleOrFloat f : Float) {
self.init(float : f)
}
convenience init(cgFloat : CGFloat) {
self.init(doubleOrFloat: cgFloat.native)
}
// NSNumber -> CGFloat
private func doubleOrFloatValue() -> Double {
return self.doubleValue
}
private func doubleOrFloatValue() -> Float {
return self.floatValue
}
var cgFloatValue : CGFloat {
return CGFloat(floatLiteral: doubleOrFloatValue())
}
}
There are two private "helper" init methods with the same external
parameter name doubleOrFloat
but different parameter types. From the actual
type of cgFloat.native
the compiler determines which one to call
in
convenience init(cgFloat : CGFloat) {
self.init(doubleOrFloat: cgFloat.native)
}
Same idea in the accessor method. From the type of self.native
the compiler determines which of the two doubleOrFloatValue()
methods to call in
var cgFloatValue : CGFloat {
return CGFloat(floatLiteral: doubleOrFloatValue())
}
ObjectiveC test if int is long or not / CGFloat is float or double
C11 has introduced a new feature "Generic selection" that can be used to
let the compiler choose the right method, depending on the type of CGFloat
.
Written as a NSScanner
category method:
@implementation NSScanner (MyCategory)
-(BOOL) myScanCGFloat:(CGFloat *)cgFloatValue
{
return _Generic(*cgFloatValue,
double: [self scanDouble:(double *)cgFloatValue],
float: [self scanFloat:(float *)cgFloatValue]);
}
@end
Remarks:
- The
_Generic
keyword is described in "6.5.1.1 Generic selection" of the C11 standard (http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf). Another description is here:
http://www.robertgamble.net/2012/01/c11-generic-selections.html. - Selecting the matching code is done by the compiler, not at runtime.
- The selection checks if
CGFloat
is compatible tofloat
ordouble
,
not if the current target architecture is 32-bit or 64-bit. - This solution does not depend on any preprocessor macros.
- As of Xcode 5.0.2, Clang supports the
_Generic
keyword, even in the default GNU99 mode. I have not tested earlier Xcode/Clang versions.
Previous answer: One possible solution would be do mimic the definition of CGFloat
and let the preprocessor choose the correct version:
CGFloat f;
#if __LP64__
[scanner scanDouble:&f];
#else
[scanner scanFloat:&f];
#endif
Or you define a custom macro:
#if __LP64__
#define scanCGFloat scanDouble
#else
#define scanCGFloat scanFloat
#endif
// ...
CFFloat f;
[scanner scanCGFloat:&f];
Alternatively, use a temporary variable:
double tmp;
[scanner scanDouble:&tmp];
f = tmp;
What's the difference between NSNumber and NSInteger?
The existing answers are useful; adding to them:
Yes, NSUInteger
gives twice the range among positive integers as NSInteger
, but I think another critical reason to choose between the two is simply to distinguish among cases where negative values simply do not make sense.
Example: the return value of NSArray
's count
method is an NSUInteger
, which makes sense since we cannot have an array with a negative number of elements. When the coder knows it's unsigned, he/she has more freedom to perform operations that might be unreliable in the signed case, including bitwise operations such as shifting. This blog post talks more about signed vs unsigned.
My guess about CGFloat
vs NSFloat
(which doesn't exist): It might be the case that the designers of the NeXTStep-named code elements simply didn't need to specify too many float values, outside of time intervals. So they gave NSTimeInterval
, which is a floating-point type, but that is clearly intended for use with time intervals. And, frankly, it's great to have that type because you know it's always meant to be in seconds without having to deal with a struct. When you move into the graphics world (where Core Graphics lives), suddenly floats are all around you, hovering in the air (haha). So it makes sense to introduce a CGFloat
there. This paragraph is all "educated speculation."
Also, just to be clear about why you might use NSInteger
etc instead of primitive types: Because this way it's easier to write portable code that takes full advantage of the machine architecture. For example, a CGFloat
uses 32 bits on some machines and 64 bits on others, depending largely on how much of an efficiency gap there is on those machines for those sizes. In some cases, there's no real speedup for using 32 bits vs 64 bits, so you might as well use 64 bits. If you've declared things as CGFloat
's, you suddenly get that extra precision "for free" when you recompile.
And, as iKenndac has pointed out, NSNumber
is a wrapper class for all of these (and other primitive or quasi-primitive types like the BOOL
) which enables you to include it in your NSArray
s and NSDictionary
s, archive them more easily, and do other things that NSObject
s can do.
What is the equivalent of NSNotFound for floats
You could use not a number (NaN
).
See nan()
, nanf()
and isnan()
.
However for these issues, where there is no clearly defined non-value (it's worse with integers), then I prefer to use the following method semantics:
- (BOOL)parseString:(NSString *)string
toFloat:(CGFloat *)value
{
// parse string here
if (parsed_string_ok) {
if (value)
*value = parsedValue;
return YES;
}
return NO;
}
Creating An Array of CGFloat for Gradient Locations
NSGradient's documentation states that locations
parameter should be of type const CGFloat*
, so you can't use NSArray*
. The following should work:
// Allocate a C-array with the same length of colorArray2
CGFloat* pArray = (CGFloat*)malloc(colorArray2.count * sizeof(CGFloat));
for (NSInteger i2 = 0; i2 < colorArray2.count; i2++) {
// Extract location
NSString* p = [[colorArray2 objectAtIndex:i2] objectForKey:key2e];
pArray[i2] = [p doubleValue];
}
// Do whaterver with pArray
...
// Remember to free it
free(pArray);
Swift Double is Not Convertible to CGFloat
Convert the values that need to be CGFloat to a CGFloat.
path.addArcWithCenter(center, radius: CGFloat(radius), startAngle: CGFloat(0.0), endAngle: CGFloat(M_PI) * 2.0, clockwise: true)
startAngle probably shouldn't need to be converted though if you're just passing a literal. Also note that this isn't a C style cast, but actually converting between different Swift Types.
Edit: Looking at your whole function, this works.
func drawCircle() {
// Drawing code
var bounds:CGRect = self.view.bounds
var center = CGPoint()
center.x = bounds.origin.x + bounds.size.width / 2.0
center.y = bounds.origin.y + bounds.size.height / 2.0
var radius = (min(bounds.size.width, bounds.size.height) / 2.0)
var path:UIBezierPath = UIBezierPath()
path.addArcWithCenter(center, radius: CGFloat(radius), startAngle: CGFloat(0.0), endAngle: CGFloat(Float(M_PI) * 2.0), clockwise: true)
path.stroke()
}
What's the difference between using CGFloat and float?
As @weichsel stated, CGFloat is just a typedef for either float
or double
. You can see for yourself by Command-double-clicking on "CGFloat" in Xcode — it will jump to the CGBase.h header where the typedef is defined. The same approach is used for NSInteger and NSUInteger as well.
These types were introduced to make it easier to write code that works on both 32-bit and 64-bit without modification. However, if all you need is float
precision within your own code, you can still use float
if you like — it will reduce your memory footprint somewhat. Same goes for integer values.
I suggest you invest the modest time required to make your app 64-bit clean and try running it as such, since most Macs now have 64-bit CPUs and Snow Leopard is fully 64-bit, including the kernel and user applications. Apple's 64-bit Transition Guide for Cocoa is a useful resource.
How to round CGFloat
There are already standard functions with behaviors you might need in <math.h>
such as: floorf
, ceilf
, roundf
, rintf
and nearbyintf
(lasf 'f' means "float" version, versions without it are "double" versions).
It is better to use standard methods not only because they are standard, but because they work better in edge cases.
2013 Update (jessedc)
iOS is no longer only 32 bit. There are a number of other answers to this question that are now more relevant.
Most answers mention importing tgmath.h
- https://stackoverflow.com/a/5352779/184130
- https://stackoverflow.com/a/7695011/184130
Casting CGFloat to Float in Swift
You can use the Float()
initializer:
let cgFloat: CGFloat = 3.14159
let someFloat = Float(cgFloat)
Related Topics
How to Tap on a Specific Point Using Xcode Uitests
Sbstatusbarcontroller Instance
How to Save List of Object in User Default
Playing Back Audio Using Avaudioplayer iOS 7
How to Check Version of a Cocoapods Framework
Development Team Not Showing in Xcode
How to Remove the Authorization Prompt from Command-Line Instances of Instruments (Xcode)
Open Uisplitviewcontroller to Master View Rather Than Detail
How to Add a Button with Click Event on Uitableviewcell in Swift
iOS How to Detect Programmatically When Top View Controller Is Popped
Fbsdkloginmanager Loginwithpublishpermissions Always Returns Iscancelled=Yes
Undefined Symbols for Architecture I386: "_Objc_Class_$_Zipexception", Referenced From: Error
Xcode 8.1 Push Notifications in Swift 2.3 with Firebase Integration Not Getting
Why Is This Code Not Recognising the Nsstring as Being Equal
Xcode 10, Command Codesign Failed with a Nonzero Exit Code
Uiview Touch Event in Controller