Confusion due to Swift lacking implicit conversion of CGFloat

后端 未结 4 616
你的背包
你的背包 2020-12-16 02:10

Trying to do arithmetic in a function that returns `CGFloat, I get an error:

Couldn\'t find overload for \'/\' that accepts supplied arguments

相关标签:
4条回答
  • 2020-12-16 02:43

    This should fix the error:

    func kDCControlDegreesToRadians(x : CGFloat) -> CGFloat
    {
        return (CGFloat(M_PI) * (x) / 180.0)
    }
    

    The reason the error is occurring is because x is explicitly declared to be a CGFloat, while M_PI has the type CDouble, as seen in the declaration:

    var M_PI: CDouble { get } /* pi             */
    

    Because of this, you need to cast M_PI to type CGFloat so it matches the type of x (as I have done in the code above). This way, there is no conflict in operating on different types.

    Note that, contrary to what is stated in other answers (and as @Cezar commented), you do not need to explicitly cast 180.0 to the CGFloat type, because it is a literal, and does not have an explicit type, so will automatically be converted to CGFloat without needing a manual cast.

    0 讨论(0)
  • 2020-12-16 02:45

    This is a problem with double to float conversion.

    On a 64-bit machine, CGFloat is defined as double and you will compile it without problems because M_PI and x are both doubles.

    On a 32-bit machine, CGFloat is a float but M_PI is still a double. Unfortunately, there are no implicit casts in Swift, so you have to cast explicitly:

    return (CGFloat(M_PI) * (x) / 180.0)
    

    The type for 180.0 literal is inferred.

    In Swift 3

    M_PI is deprecated, use CGFloat.pi instead:

    return (x * .pi / 180.0)
    
    0 讨论(0)
  • 2020-12-16 02:50

    In this specific case I have a cute trick to recommend

    let π = CGFloat(M_PI)

    Unicode everywhere, and π is easy to get to with Opt+P

    0 讨论(0)
  • 2020-12-16 02:51

    Its best to abstract away the complexity. First create an extension

    extension Double {
        /** Converts the specified value in degrees into radians. */
        func degrees() -> CGFloat {
            return CGFloat(self) * CGFloat(M_PI / 180.0)
        }
    }
    

    then use it in your code such as the following example

    let angle = 30.0.degrees()
    let transform = CGAffineTransformRotate(self.sliderControl.transform, angle);
    

    At first I was reluctant to extend Double because I don't like creating a custom tailored use of the language (from coding horrors found in C++). However, practical experience has shown this to being a way of abstraction natural to the language.

    0 讨论(0)
提交回复
热议问题