7

I have a simple switch-statement that is not that simple.

switch(bubble?.name){ //bubble is SKPhysicsBody
    case "largeBubble": // <= error
        newBubbleSize = "medium"
        break;
    default:
        newBubbleSize = "large"
        break;
}

Here I get error that I mentioned in title Binary operator '~=' cannot be applied to operands of type 'String' and 'String?'. And I have no clue why it is a problem that one of them is an optional.

Jurik
  • 3,244
  • 1
  • 31
  • 52

4 Answers4

8

Because of Optional Chaining, bubble?.name has type String?. You have a few options:

  • Use "largeBubble"? in your case expression (Swift 2+ only).
  • Check for nil before doing your switch, so the switch argument will be a String instead of String?.
  • Use bubble!.name (or bubble.name if it's a SKPhysicsBody!) if you are absolutely sure that it won't be nil
jtbandes
  • 115,675
  • 35
  • 233
  • 266
  • Option #4: `switch(bubble?.name ?? "unknown") { ... }`. – Martin R May 30 '15 at 18:14
  • Sure, but then you will be doing an unnecessary comparison with the string "unknown" in some cases :) Of course, it's probably so fast that it doesn't matter... – jtbandes May 30 '15 at 18:15
  • `bubble!.name` didn't work - well, only in combination with `some()`. Thought that's why there's always a default as well ... if name is not set. – Jurik May 30 '15 at 18:22
  • @Jurik exactly what type is `bubble`? (`SKPhysicsBody` or `SKPhysicsBody?` or perhaps `!`) – jtbandes May 30 '15 at 18:23
  • It's `bodyA` or `bodyB` from `SKPhysicsContact`. – Jurik May 30 '15 at 18:26
  • `bodyA` and `bodyB` are both `SKPhysicsNode!`. I am not 100% sure, but I suspect these are really never nil, so it's safe to just use `bubble.name`. That is the solution I would recommend. – jtbandes May 30 '15 at 18:30
3

As @jtbandes said, the problem is the result of bubble?.name having type String?. An alternative solution, to the ones given, is to override the ~= operator to take a String? and String as arguments, for example:

func ~= (lhs: String, rhs: String?) -> Bool {
    return lhs == rhs
}

Or, to make it more generic:

func ~= <T: Equatable>(lhs: T, rhs: T?) -> Bool {
    return lhs == rhs
}
ABakerSmith
  • 22,759
  • 9
  • 68
  • 78
1

“Values are never implicitly converted to another type. If you need to convert a value to a different type, explicitly make an instance of the desired type.”

“let label = "The width is "
let width = 94
let widthLabel = label + String(width)”

Here width is an Integer type it has been converted to String by String(Int) function

Pias
  • 218
  • 1
  • 2
  • 13
0

In Swift 2.0 (sender: UIButton) then ! for the switch string works.

let operation = sender.currentTitle!

In Swift 2.0, (sender: AnyObject) then !! for the switch string works.

let operation = sender.currentTitle!!

the mistake which i made is using AnyObject instead of UIButton.

@IBAction func operate(sender: AnyObject) {
        let operation = sender.currentTitle!!

        if userIsInTheMiddleOfTypeingNumber{
            enter()
        }

        switch operation{
            case "×":
                if operandStack.count >= 2{
                    displayValue = operandStack.removeLast() * operandStack.removeLast()
                }

                break
//            case "÷":
//                break
//            case "+":
//                break
//            case "−":
//                break
           default:
                break
        }

    }
Ranjithkumar
  • 697
  • 6
  • 16