Convert between CGFloat and NSNumber without unnecessary promotion in Double

As we all know CGFloat(which is ubiquitous in CoreGraphics, UIKit, etc.), it can be a 32-bit or 64-bit floating point number, depending on the processor architecture.

In C, CGFloatthis is typealias before floator double, in Swift is defined as struct CGFloatwith a native( floator double).

It has been repeatedly observed that a NSNumbercan be created from and converted to floatand double, but there are no similar conversions from and to CGFloat. A general tip (for example, Convert CGFloat to NSNumber in Swift ) is to convert viadouble

CGFloat <--> Double <--> NSNumber

Example:

let c1 = CGFloat(12.3)
let num = NSNumber(double: Double(c1))
let c2 = CGFloat(num.doubleValue)

, . 64-, CGFloat/Double , , .

, CGFloat double 32- .

(, CGFloat ?):

extension NSNumber {
    convenience init(cgFloatValue value : CGFloat) {
        #if arch(x86_64) || arch(arm64)
            self.init(double: value.native)
        #else
            self.init(float: value.native)
        #endif
    }
}

, Swift , Intel ARM? .

CGFLOAT_IS_DOUBLE (, NSNumber CGFloat):

    if CGFLOAT_IS_DOUBLE != 0 {
        // ...
    } else {
        // ...
    }

, " " .

, :

  • CGFloat NSNumber , , double?

, "" . ( Q & A) double .

"-" , Q & A-style. , !

+5
2

: CGFloat NSNumber :

let c1 = CGFloat(12.3)
let num = c1 as NSNumber
let c2 = num as CGFloat

CGFloat Swift 2 Swift 3.


( - ): , . NSNumber CFNumber ( CGFloat NSNumber? Objective-C). , CFNumber CGFloat:

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
    }
}

. : init class method.

:

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())
    }
}

"" init doubleOrFloat, . cgFloat.native ,

    convenience init(cgFloat : CGFloat) {
        self.init(doubleOrFloat: cgFloat.native)
    }

. self.native , doubleOrFloatValue()

    var cgFloatValue : CGFloat {
        return CGFloat(floatLiteral: doubleOrFloatValue())
    }
+11
let num = NSNumber(double: 1.0)
let c: CGFloat? = CGFloat(exactly: num)

.

0

Source: https://habr.com/ru/post/1620222/


All Articles