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 make74/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 optionalAnyObject
(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
Playing a Sound in a Swift Playground
Why Is Generic Specialization Lost Inside a Generic Function
Load Desktop Version Wkwebview iOS 9
Nsurlerrordomain with Code=-1100
How to Update a Value in a Nested Dictionary Given Path Fragment in Swift
Why Is an Object Not Being Decoded
How to Do an If-Else Comparison on Enums with Arguments
Does Swift Compile to Native Code
How to Debug "Precondition Failure" in Xcode
Map and Flatmap Difference in Optional Unwrapping in Swift 1.2
Print the Nstableview's Row Number of the Row Clicked by the User
Swiftui Label Text and Image Vertically Misaligned
Controlling Size of Texteditor in Swiftui
Turn for in Loops Local Variables into Mutable Variables
Injecting a New Stylesheet into a Website via Uiwebview Using iOS8 Swift Xcode 6