Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift binary operator '+' cannot be applied to two CGFloat operands

I am writing a function in Swift to detect which hexagon I am clicking on. But I ran into a peculiar error message stating that I cannot add two CGFloats. Whatever I did, e.g. changing let to var, declare and assign separately, did not work. I guess there must be something else wrong, but I cannot find it. The code is as follows:

func pointToCoordinate(position: CGPoint) -> (Int, Int) {
        var gridHeight = 2 * singleRadius / sqrt(CGFloat(3)) * 1.5
        var gridWidth = 2 * singleRadius
        var halfWidth = singleRadius

        var relativePosition = CGPoint(x: position.x - totalRadius / 2, y: position.y - totalRadius / 2)
        println((relativePosition.y / gridHeight))
        var row = -(cgfloatToInt)(relativePosition.y / gridHeight)
        var column: Int

        println((relativePosition.x + halfWidth * CGFloat(row + 1)) / (gridWidth))
        column = cgfloatToInt((relativePosition.x + halfWidth * CGFloat(row + 1)) / (gridWidth))

//        var innerY: CGFloat = CGFloat(relativePosition.y) + CGFloat(gridHeight * row)
        var innerX = relativePosition.x
        var innerY = relativePosition.y

        innerY = innerY - CGFloat(gridHeight * row)

        println((innerX, innerY))
        return (column, row)
    }

Error Message

like image 819
Colliot Avatar asked Jun 06 '15 00:06

Colliot


5 Answers

The error message is wrong. The problem is that you are trying to multiply an Int and a CGFloat.

Replace:

innerY = innerY - CGFloat(gridHeight * row)

with:

innerY = innerY - gridHeight * CGFloat(row)

The answer above is for the current version of your code. For the commented out version that corresponds to the error message you posted:

Replace:

var innerY: CGFloat = CGFloat(relativePosition.y) + CGFloat(gridHeight * row)

with

var innerY: CGFloat = CGFloat(relativePosition.y) + gridHeight * CGFloat(row)
like image 63
vacawama Avatar answered Nov 19 '22 04:11

vacawama


Looking through all the answers, castings, conversion and extensions, I think the best solution yet to say for Swift is Operator Overload. Code sample below for Swift 3.0:

/// overloads -/+ between a cgfloat on the left and an int/double on the right
func - (left: CGFloat, right: Double) -> CGFloat {
    return left - CGFloat(right);
}

func - (left: CGFloat, right: Int) -> CGFloat {
    return left - CGFloat(right);
}

func + (left: CGFloat, right: Double) -> CGFloat {
    return left + CGFloat(right);
}

func + (left: CGFloat, right: Int) -> CGFloat {
    return left + CGFloat(right);
}

Put this into a global place OUTSIDE of any class. See magic occurs.

like image 26
Michael Shang Avatar answered Nov 19 '22 06:11

Michael Shang


Indeed, there is something else wrong, this works:

import QuartzCore

let a:CGFloat = 1
let b:CGFloat = 2

let c = a + b
var innerY: CGFloat = CGFloat(1.0) + CGFloat(2.0)

and CGFloat implements the FloatingPointType type

like image 3
Chris Conover Avatar answered Nov 19 '22 06:11

Chris Conover


Late to join. Based on vacawama's answer, you all know the problem is not having the same data type.
CGFloat needs to be written multiple times sometimes. I found this easier via extension. So sharing an answer. You can create a simple extension like below. Ofcourse, this extension can be further modified.

import CoreGraphics
extension Int {
    var cgf: CGFloat { return CGFloat(self) }
    var f: Float { return Float(self) }
}

extension Float {
    var cgf: CGFloat { return CGFloat(self) }
}

extension Double {
    var cgf: CGFloat { return CGFloat(self) }
}

extension CGFloat {
    var f: Float { return Float(self) }
}

Now we can write

innerY = innerY - gridHeight * row.cgf
like image 1
san Avatar answered Nov 19 '22 06:11

san


iOS 15, Swift 5.x

I had this problem, was solved by unwrapping the value... the floats in my case were optionals.

like image 1
user3069232 Avatar answered Nov 19 '22 04:11

user3069232