Swift Operator "*" Throwing Error on Two Ints

Swift operator * throwing error on two Ints

The error is misleading. The problem is actually the attempt to assign an Int value to a CGFloat variable.

This will work:

scrollView.contentSize.height = CGFloat(325 * globals.defaults.integer(forKey: "numCards"))

The cause of the misleading error (thanks to Daniel Hall in the comments below) is due to the compiler choosing the * function that returns a CGFloat due to the return value needed. This same function expects two CGFloat parameters. Since the two arguments being provided are Int instead of CGFloat, the compiler provides the misleading error:

Binary operator '*' cannot be applied to two 'Int' operands

It would be nice if the error was more like:

Binary operator '*' cannot be applied to two 'Int' operands. Expecting two 'CGFloat' operands.

Binary operator + cannot be applied to two int operands

1) The first code works because String has an init method that takes an Int. Then on the line

let widthLabel = label + String(width)

You're concatenating the strings, with the + operator, to create widthLabel.

2) Swift error messages can be quite misleading, the actual problem is Int doesn't have a init method that takes a String. In this situation you could use the toInt method on String. Here's an example:

if let h = height.toInt() {
let heightNumber = number + h
}

You should use and if let statement to check the String can be converted to an Int since toInt will return nil if it fails; force unwrapping in this situation will crash your app. See the following example of what would happen if height wasn't convertible to an Int:

let height = "not a number"

if let h = height.toInt() {
println(number + h)
} else {
println("Height wasn't a number")
}

// Prints: Height wasn't a number

Swift 2.0 Update:

Int now has an initialiser which takes an String, making example 2 (see above):

if let h = Int(height) {
let heightNumber = number + h
}

Binary operator ' ' cannot be applied to two 'Int?' operands

If you look at the declaration for Int's initializer that takes a String, you can see by the ? after init that it returns an optional:

convenience init?(_ description: String)

This means you have to unwrap it before you can do most things with it (== is an exception, since the Optional type has an overload for that operator).

There are four main ways to unwrap your optionals:

1: If let

if let goalOne = Int(someString) {
// do something with goalOne
}

2: Guard let

guard let goalOne = Int(someString) else {
// either return or throw an error
}

// do something with goalOne

3: map and/or flatMap

let someValue = Int(someString).map { goalOne in
// do something with goalOne and return a value
}

4: Provide a default value

let goalOne = Int(someString) ?? 0 // Or whatever the default value should be

If you unwrap all your optionals, you'll be able to compare them as you expect.

Swift 3 error: Binary operator '/' cannot be applied to two 'int' operands

The UIColor constructor takes four CGFloat parameters.

UIColor(red: 74/255, green: 24/255, blue: 141/255, alpha: 1)

compiles because CGFloat conforms to the ExpressibleByIntegerLiteral
protocol. From the context the compiler tries to make
74/255 a CGFloat, and interprets all the numbers as CGFloat
literals, and / as the CGFloat division operator.

That does not work with

var colorRGB = 74
UIColor(red: colorRGB/255, green: 24/255, blue: 141/255, alpha: 1)

There is no context for the 74 literal, so that it is taken
as an Int by default. But there is no
suitable division operator to make colorRGB/255 a CGFloat.

You have to define the variable explicitly with the correct type:

var colorRGB: CGFloat = 74
UIColor(red: colorRGB/255, green: 24/255, blue: 141/255, alpha: 1)

Remark: This would also compile:

var colorRGB = 74
UIColor(red: CGFloat(colorRGB/255), green: 24/255, blue: 141/255, alpha: 1)

But then colorRGB/255 becomes the integer division and evaluates
to zero, compare Strange Swift numbers type casting.

Binary operator '+' cannot be applied to two 'T' operands

Swift doesn't know that the generic type T has a '+' operator. You can't use + on any type: e.g. on two view controllers + doesn't make too much sense

You can use protocol conformance to let swift know some things about your type!

I had a go in a playground and this is probably what you are looking for :)

protocol Addable {
func +(lhs: Self, rhs: Self) -> Self
}

func add<T: Addable>(num1: T, _ num2: T) -> T {
return num1 + num2
}

extension Int: Addable {}
extension Double: Addable {}
extension Float: Addable {}

add(3, 0.2)

Let me know if you need any of the concepts demonstrated here explained

Swift sortinplace binary operator cannot be applied to two nsnumber operands

Crap I am a moron, as soon as I posted this I realized what I wanted to do. NSNumber has an intValue function! Just needed to change it to

people.sortInPlace{($0.id.intValue > $1.id.intValue)}

concatenate in swift: Binary operator '+' cannot be applied to operands of type 'String' and 'AnyObject'

The error message might be misleading in the first example

if currentUser["employer"] as! Bool == false { 
print("employer is false: "+currentUser["employer"] as! Bool)
}

In this case, the error message is supposed to be

binary operator '+' cannot be applied to operands of type 'String' and 'Bool'

because currentUser["employer"] as! Bool is a non-optional Bool and cannot be implicitly cast to String

Those examples

print("employer: "+currentUser["employer"])
print("employer: \(currentUser["employer"])")

don't work because

  • In the first line, currentUser["employer"] without any typecast is an optional AnyObject (aka unspecified) which doesn't know a + operator.
  • In the second line, the string literal "employer" within the String interpolated expression causes a syntax error (which is fixed in Xcode 7.1 beta 2).

Edit:

This syntax is the usual way.

let isEmployer = currentUser["employer"]
print("isEmployer: \(isEmployer)")

Or alternatively, you can write

print("employer is " + String(currentUser["employer"] as! Bool))

Lesser than or greater than in Swift switch statement

Here's one approach. Assuming someVar is an Int or other Comparable, you can optionally assign the operand to a new variable. This lets you scope it however you want using the where keyword:

var someVar = 3

switch someVar {
case let x where x < 0:
print("x is \(x)")
case let x where x == 0:
print("x is \(x)")
case let x where x > 0:
print("x is \(x)")
default:
print("this is impossible")
}

This can be simplified a bit:

switch someVar {
case _ where someVar < 0:
print("someVar is \(someVar)")
case 0:
print("someVar is 0")
case _ where someVar > 0:
print("someVar is \(someVar)")
default:
print("this is impossible")
}

You can also avoid the where keyword entirely with range matching:

switch someVar {
case Int.min..<0:
print("someVar is \(someVar)")
case 0:
print("someVar is 0")
default:
print("someVar is \(someVar)")
}


Related Topics



Leave a reply



Submit