user2909913
user2909913

Reputation: 4149

Custom Segue in Swift

@objc(SEPushNoAnimationSegue)
class SEPushNoAnimationSegue: UIStoryboardSegue {
    override func perform () {
      self.sourceViewController.navigationController.pushViewController(self.destinationViewController, animated:false)
    }
}

In the above code, I have 2 questions: 1). it has a compile error: 'UINavigationController!' does not have a member named 'pushViewController'

But in that class, it did has a pushViewController method.

2). I have to add the annotation: @objc(SEPushNoAnimationSegue), otherwise, in storyboard, it only recognize the random generated name, like, _tcxxxxSEPushNoAnimationSegue.

why these 2 issues happen here?

Upvotes: 15

Views: 17453

Answers (4)

jakedunc
jakedunc

Reputation: 982

Swift 3.0:

import UIKit

class CustomNoAnimationSegue: UIStoryboardSegue {

    override func perform() {
        if let navigation = source.navigationController {
            navigation.pushViewController(destination, animated: false)
        }
    }
}

Upvotes: 0

Jean Le Moignan
Jean Le Moignan

Reputation: 22236

Issue #1

UIStoryboardSegue has an irritating flaw: its sourceViewController and destinationViewController properties are typed as AnyObject! (that's the case even in Objective-C (Id type)) and not as UIViewController, as it should be.

That same flaw creates havoc in your perfect and simple code. Here's how to rewrite it in order to fix the compile errors:

@objc(SEPushNoAnimationSegue)
class SEPushNoAnimationSegue: UIStoryboardSegue {
    override func perform () {
        let src = self.sourceViewController as UIViewController
        let dst = self.destinationViewController as UIViewController
        src.navigationController.pushViewController(dst, animated:false)
    }
}

NOTE: Apple fixed this thing in iOS 9. sourceViewController and destinationViewController are now correctly declared as UIViewController.

Issue #2

The Swift compiler stores its symbols using its own name mangling, and good ol' Objective-C does not recognize it in Xcode. Using an explicit @obj() solves the issue.

Upvotes: 35

Mike Miller
Mike Miller

Reputation: 11

Even Better:

import UIKit

class CustomSegue: UIStoryboardSegue {
    override func perform() {
        self.sourceViewController.presentViewController(self.destinationViewController as UIViewController, animated: false, completion: nil)
    }
}

Upvotes: 1

fabian
fabian

Reputation: 5463

This works fine for me

@objc(SEPushNoAnimationSegue) class SEPushNoAnimationSegue: UIStoryboardSegue {

override func perform() {
    let sourceViewController = self.sourceViewController as UIViewController
    let destinationViewController = self.destinationViewController as UIViewController

    sourceViewController.presentViewController(destinationViewController, animated: true, completion: nil)
}

}

Upvotes: 5

Related Questions