Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

iOS Build a Playlist Browser with Swift Refactoring Our Code Passing Playlist Objects Using Segues

Mikhail Damiani
PLUS
Mikhail Damiani
Courses Plus Student 4,175 Points

Swift Dynamic Cast Failed

Getting a runtime error "Swift dynamic cast failed"

It seems to be happening after clicking the main navigation image on this line on the PlaylistMasterController:

let playlistImageView = sender!.view as UIImageView

Has anyone else encountered this?

I got a problem at that line too

Richard Price
Richard Price
2,050 Points

yup same here cannot progress and its so FRUSTRATING

13 Answers

Pasan Premaratne
STAFF
Pasan Premaratne
Treehouse Teacher

Richard Price

Your tap gesture recognizers need to be added to the image views and not the main view. If you select a gesture recognizer in the document outline and check the connections in the Connections inspector (in the utilities panel), under referencing outlet collections it should show that the "gestureRecognizers" is connected to "placeholder". Placeholder is my image name in this example.

gesture recognizer

What I'm guessing is happening is that you added the gesture recognizer to the view instead of the image view and when you reference sender.view it doesn't return an image view making your cast fail.

As an aside, my name is "Pasan" and you need to tag me using the @+name function of the forum to bring a post to my attention. There are over a hundred posts per day and I simply can't get to each one unless tagged.

I think for many of us your guess is correct, with great respect, for many of us to all make similar time consuming error (not withstanding errors are good for learning) it says something about demonstrating technique and the visual ambiguaty to the unitiated, technique shouldn't assume what is clearly obvious to the educated as may not be to others. I felt until I read this I duplicated your demonstration to the nth degree when clearly I did not, even after reviewing back as far as that video. If instructors catered for the lowest common denominator ( me for example) we'd all be nailing this with less frustration and less forum posts would be posted to annoy you with. Rant over. Was still a good learning experience. Good to know about the @+name too, was unaware. :)

Pasan Premaratne
Pasan Premaratne
Treehouse Teacher

Kaitlan Lang,

Certainly not annoyed and happy to help fix bugs. I think there's a slight misconception here about software development and getting your code to work like this. Debugging isn't something that disappears as you get better at programming. In fact, as you write more complex code, your bugs may be even harder to spot and the learning process here is figuring out how to resolve those issues yourself.

Programmers spend more time reasoning about how their code works and debugging existing code than writing any new code. Trying things out to the nth degree, as you say, is a big part of this. When it comes to course creation we can't always show the possible ways it could go wrong - simply because the course would be hours longer than it already is. For the one error that you encountered (that this post solves) there are lots of other errors that could occur with this one specific line of code.

We try and maintain that balance although it's often difficult to do it contextually. The issue in this case ("orphaned outlets") are covered in the How to Build a Simple iPhone App course so I specifically chose to cover new content here. But..point noted! I'll add it as a note on the video :)

and how can I fix this bug, to change the Referencing Outlet Collections from "gestureRecognizers -> View" to "gestureRecognizers -> placeholder" pls tell me how to do

Pasan Premaratne
Pasan Premaratne
Treehouse Teacher

Mummy Lao

Where it says "gestureRecognizers -> View", press on the tiny X to get rid of that connection. Then control drag from the gestureRecognizer in the document outline over to an image view. Only let go when you see the placeholder image highlighted. You can even drag it from the gestureRecognizer in the document outline to the image view in the outline as well

Thank you very much Kaitlan Lang, now it's work :)

Mikhail Damiani
PLUS
Mikhail Damiani
Courses Plus Student 4,175 Points

I determined that the problem was actually coming from incorrectly connecting the playlistImageView outlets. For anyone else struggling with a similar problem, I solved this by checking the connections tab (next to size and attributes tabs) and noticing that a playlistImageView had not been configured correctly

Richard Price
Richard Price
2,050 Points

what do you mean by this? when I remove the code added from this video it works fine (indicating that the playlist outlet is fine) the issue is with down casting to a UIImageView. It doesn't like it and I can't understand how it works in this video but not on my X code. We need an answer from Prasad....please help

Eliot Murton
Eliot Murton
7,315 Points

Hi Pasan Premaratne and everybody else. I see what you mean about having linked it to the view rather than the image view. I delete this link then ctrl drag from gesture recognizer to the placeholder. When I do this the drop down that appears is headlined "Outlets" with only one option of "delegate". Why is this? I can't get past this point.

Hi Eliot Murton ! Did you solve your problem? I am also facing the same issue. please help me out if you have solved it.

Thanks

Eliot Murton
Eliot Murton
7,315 Points

Never mind. I figured out how to do it by ctrl clicking and dragging from the option box that appears then. All works so far. AWESOME!!!!!!!! (I'm a little bit excited as I was 3 seconds away from crying in a corner somewhere). Peace.

Glad you got it fixed, Eliot!

You know where we are if you need a hand at any point. Just shout in the forum!

Steve.

Wissile Sogoyou
Wissile Sogoyou
4,742 Points

Had the same issue but got it to work in the end! Apple keep upgrading Xcode and changing swift syntax, so its not Pasan's fault. All you need to do is add a bang: "!" right after UIImageView like this Solution: let playlistImageView = sender!.view as! UIImageView!

and voila !

Marcelo Farjalla
Marcelo Farjalla
3,241 Points

Okay. So I keep seeing Xcode telling me I have to add a bang(!) after 'as' and Pasan's example doesn't show any such thing. I am assuming as mentioned in this comment that it's because Apple changed things after the video was created. Thanks.

Yes, Marcelo, the Swift language changed making the bang usage different.

Steve.

Can you post the rest of the code in that Controller, please?

Jens Hagfeldt
Jens Hagfeldt
16,548 Points

Did you check what object sender is before casting it's view as an UIImageView?

In that step I think that we first made sure that sender is one of our image views by checking it's segue identifier... So in other words do they all have the segue identifier that you ask for?

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "showPlaylistDetailSegue" {

            let playlistImageView = sender!.view as UIImageView
            if let index = find(playlistArray, playlistImageView) {
                let playlistDetailController = segue.destinationViewController as PlaylistDetailViewController
                playlistDetailController.playlist = Playlist(index: index)
            }
        }
    }
Richard Price
Richard Price
2,050 Points

happening for me and my controller is connected correctly. Does anyone have a fix please?

Richard Price
Richard Price
2,050 Points

soon as this code is added the app crashes and complains about casting

works fine before this. Any ideas anyone on this?

   override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

      if segue.identifier == "showPlaylistDetailSegue" {

          let playlistImageView = sender!.view as UIImageView

            if let index = find(playlistArray, playlistImageView) {


               let playListDetailController = segue.destinationViewController as PlaylistDetailViewController

               playListDetailController.playlist = Playlist(index: index)

           }

       }

   }
Richard Price
Richard Price
2,050 Points

PRASAD...please help your code has been copied correctly but this is the issue its been copied therefore making it difficult to debug. As soon as the above code is added the app falls down which means everything was fine up until this video with downcastinf to UIIMAGEVIEW and adding the optional binding

unable to progress onto the next video and very frustrating

David Sparks
PLUS
David Sparks
Courses Plus Student 8,657 Points

libswiftCore.dylib`swift_dynamicCastObjCClassUnconditional: 0x103510620: pushq %rbp 0x103510621: movq %rsp, %rbp 0x103510624: pushq %rbx 0x103510625: pushq %rax 0x103510626: movq %rsi, %rcx 0x103510629: movq %rdi, %rbx 0x10351062c: xorl %eax, %eax 0x10351062e: testq %rbx, %rbx 0x103510631: je 0x10351064c ; swift_dynamicCastObjCClassUnconditional + 44 0x103510633: movq 0x82756(%rip), %rsi ; "isKindOfClass:" 0x10351063a: movq %rbx, %rdi 0x10351063d: movq %rcx, %rdx 0x103510640: callq 0x1035131ca ; symbol stub for: objc_msgSend 0x103510645: testb %al, %al 0x103510647: movq %rbx, %rax 0x10351064a: je 0x103510653 ; swift_dynamicCastObjCClassUnconditional + 51 0x10351064c: addq $0x8, %rsp 0x103510650: popq %rbx 0x103510651: popq %rbp 0x103510652: retq
0x103510653: leaq 0xcdc8(%rip), %rax ; "Swift dynamic cast failed" 0x10351065a: movq %rax, 0x8ae57(%rip) ; gCRAnnotations + 8 0x103510661: int3
0x103510662: nopw %cs:(%rax,%rax)

I've try to change the "gesture recognition" connection but I still can't tap the image in the IOS simulator and my Xcode version is 6.1.3.

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "showPlaylistDetailSegue" {

            let playlistImageView = sender!.view as! UIImageView
            if let index = find(playlistArray, playlistImageView){

                let playlistDetailController = segue.destinationViewController as! PlaylistDetailsViewController
                playlistDetailController.playlist = Playlist(index: index)
            }
        }
    }

    @IBAction func showPlaylistDetails(sender: AnyObject) {
        performSegueWithIdentifier("showPlaylistDetailSegue", sender: sender)
    }

this is the picture of the connection inspector from tap gesture recogniser inspector

alt text

If Pasan's fix still didn't work for you, make sure that the playlists place holder image has 'User Interaction Enabled' you'll find this checkbox by selecting the placeholder then attributes inspector. For some reason I had to go back an re-enable it.