macben
macben

Reputation: 13

self.navigationController.topViewController as HomeViewController

I have a problem with the convert objective-c to swift.

For my train, i converted MMPaper to swift, but in the property :

objective-c

- (void)interactionBeganAtPoint:(CGPoint)point
{
    // Very basic communication between the transition controller and the top view controller
    // It would be easy to add more control, support pop, push or no-op
    HASmallCollectionViewController *presentingVC = (HASmallCollectionViewController *)[self.navigationController topViewController];

    HASmallCollectionViewController *presentedVC = (HASmallCollectionViewController *)[presentingVC nextViewControllerAtPoint:point];
    if (presentedVC!=nil)
    {
        [self.navigationController pushViewController:presentedVC animated:YES];
    }
    else
    {
        [self.navigationController popViewControllerAnimated:YES];
    }
}

Swift

func interactionBeganAtPoint(point: CGPoint) {
        var presentingVC: HomeViewController! = (self.navigationController.topViewController as HomeViewController)
        var presentedVC: HomeViewController! = (presentingVC.nextViewControllerAtPoint(point) as HomeViewController)

        if (presentedVC != nil) {
            self.navigationController.pushViewController(presentedVC!, animated: true)
        } else {
            self.navigationController.popViewControllerAnimated(true)
        }
    }

The result is (problem in bold) :

libswiftCore.dylib`swift_dynamicCastClassUnconditional:
...
0x10cf7da1e:  leaq   0x36b3d(%rip), %rax       ; "Swift dynamic cast failed"
0x10cf7da25:  movq   %rax, 0xb4a2c(%rip)       ; gCRAnnotations + 8
0x10cf7da2c:  int3   
**0x10cf7da2d:  movq   %rdi, %rax**
.....

You have an idea ?

Upvotes: 1

Views: 2917

Answers (1)

stefandouganhyde
stefandouganhyde

Reputation: 4554

By using the as operator, you're telling Swift that you're absolutely sure that your downcasting to HomeViewController will succeed. However, clearly presentingVC.nextViewControllerAtPoint(point) can return nil, and you can't successfully downcast nil to HomeViewController.

When downcasting may fail, use the as? operator to return an optional value of the type you're trying to downcast to.

The following should work:

func interactionBeganAtPoint(point: CGPoint) {
    let presentingVC = self.navigationController.topViewController as? HomeViewController

    if let presentedVC = presentingVC?.nextViewControllerAtPoint(point) as? HomeViewController {
        self.navigationController.pushViewController(presentedVC, animated: true)
    } else {
        self.navigationController.popViewControllerAnimated(true)
    }
}

(I've also made use of type inference to make the code more concise; when Swift sees as? HomeViewController, it figures out that the type of presentingVC must be HomeViewController?. Sorry if that was obvious.)

Upvotes: 1

Related Questions