10 Replies
      Latest reply: Feb 23, 2017 1:48 AM by Claude31 RSS
      logistes Level 1 Level 1 (0 points)

        Hi

         

        In this code

            func swipeGesture(sender: UISwipeGestureRecognizer)
            {
                let _: UISwipeGestureRecognizerDirection = .up
                let text: String
                switch sender.direction {
                case UISwipeGestureRecognizerDirection.right: text = "Right"
                case UISwipeGestureRecognizerDirection.left: text = "Left"
                case UISwipeGestureRecognizerDirection.up: text = "Up"
                case UISwipeGestureRecognizerDirection.down: text = "Down"
                default: text = "Unknown"
                }
                label.text = text
            
        
        
        
        
        
        

         

        the compiler is happy to have the .up. but in the swtich it needs the whole huge name, thus defeating the aim of keeping swift code short. The compiler message if I take out UISwipeGestureRecognizerDirection and just leave .right is:

        "Enum case 'right' not found in type 'UISwipeGestureRecognizerDirection'

         

        Is this a bug in the compiler, or is there some reason for this that I am missing?

        • Re: Why does switch require a full declaration?
          Claude31 Level 5 Level 5 (1,915 points)

          why do you deéclaire:

          let _ : UISwipeGestureRecognizerDirection = .up

           

          It seems it is nowhere used.

           

          for the switch, you should try :

           

          let dir : UISwipeGestureRecognizerDirection = sender.direction
          
          switch dir {
          case .up: 
          
          }
          

           

          PRobably the compiler has has problem with type inference.

          • Re: Why does switch require a full declaration?
            eskimo Apple Staff Apple Staff (7,530 points)

            UISwipeGestureRecognizerDirection is not an enum, it’s an option set.  Consider this:

            let _: UISwipeGestureRecognizerDirection = [.up, .down]
            let _: UISwipeGestureRecognizerDirection = [.up]
            let _: UISwipeGestureRecognizerDirection = .up
            

            The first line demonstrates that the option set can contain many values.  The second line shows the ‘standard’ way of writing a single value option.  The last line, the one you had, is a convenient way to write the second line.

            All of the above work because the type declaration establishes a scope in which the compiler can look for values.  This doesn’t work in a switch statement because a switch statement only creates that scope when you give it an enum (in the Swift grammar this is the difference between the expression-pattern and the enum-case-pattern).

            The above just covers why UISwipeGestureRecognizerDirection behaves differently than a standard enum; it doesn’t really address the issue of whether this is just a current limitation or something more fundamental.  I don’t know enough about the internals to comment on that.  I recommend you file an enhancement for this to be improved and we’ll see where that gets you.

            Please post your bug number, just for the record.

            Share and Enjoy

            Quinn “The Eskimo!”
            Apple Developer Relations, Developer Technical Support, Core OS/Hardware
            let myEmail = "eskimo" + "1" + "@apple.com"

              • Re: Why does switch require a full declaration?
                logistes Level 1 Level 1 (0 points)

                Thanks, that makes sense. I haven't fully come to grips with OptionSets yet. I had had the impression that a type didn't have to be an enum for that sort of shorter syntax to work, but I had to write it out in full even when I put this code into an extension of UISwipeGestureRecognizerDirection

                  • Re: Why does switch require a full declaration?
                    eskimo Apple Staff Apple Staff (7,530 points)

                    I had had the impression that a type didn't have to be an enum for that sort of shorter syntax to work …

                    That’s actually correct in some cases.  For example, this works:

                    if sender.direction == .up {
                        …
                    }
                    

                    because the compiler can infer the context in which to evaluate .up from the knowledge that both sides of the == operator must be the same type.  Hence my “I don’t know enough about the internals” statement above; it’s possible that the compiler could be enhanced to do this in the expression-pattern variant of the switch statement, but I don’t know enough about how the compiler works to offer an opinion on that.  OTOH, if you file an enhancement request it’ll make it’s way to someone who will know (-:

                    Share and Enjoy

                    Quinn “The Eskimo!”
                    Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                    let myEmail = "eskimo" + "1" + "@apple.com"

                      • Re: Why does switch require a full declaration?
                        Claude31 Level 5 Level 5 (1,915 points)

                        So, would

                         

                        switch sender.direction { 
                                case [.right] : text = "Right" 
                        

                         

                        work ?

                          • Re: Why does switch require a full declaration?
                            eskimo Apple Staff Apple Staff (7,530 points)

                            And indeed it does.

                            *Argh!*  I could’ve sworn I tested this approach before writing my original response but I must have messed up the test somehow.  I just re-tested it and it compiles just fine.  I then changed my standard Stream event handling code from this:

                            func stream(_ thisStream: Stream, handle eventCode: Stream.Event) {
                                …
                                switch eventCode {
                                    case Stream.Event.openCompleted:
                                        …
                                    case Stream.Event.hasBytesAvailable:
                                        …
                                    case Stream.Event.hasSpaceAvailable:
                                        …
                                    case Stream.Event.endEncountered:
                                        …
                                    case Stream.Event.errorOccurred:
                                        …
                                    default:
                                        fatalError()
                                }
                            }
                            

                            to this:

                            func stream(_ thisStream: Stream, handle eventCode: Stream.Event) {
                                …
                                switch eventCode {
                                    case [.openCompleted]:
                                        …
                                    case [.hasBytesAvailable]:
                                        …
                                    case [.hasSpaceAvailable]:
                                        …
                                    case [.endEncountered]:
                                        …
                                    case [.errorOccurred]:
                                        …
                                    default:
                                        fatalError()
                                }
                            }
                            

                            and a) it still works, and b) it’s much nicer looking.

                            Thanks for setting us straight!

                            Share and Enjoy

                            Quinn “The Eskimo!”
                            Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                            let myEmail = "eskimo" + "1" + "@apple.com"

                            • Re: Why does switch require a full declaration?
                              logistes Level 1 Level 1 (0 points)

                              Yes, thanks. I have adopted that style as well. I think we have been victims of the compiler being a bit too tricky. I don't see the need for the sytax without [ and ] to be made available.