others-how to solve Receiver has no segue with identifier with Swift 5 and xcode 11

Problem

When we try to add a connection from one view controller to another view controller, we got this error:

2020-09-28 21:17:34.945767+0800 Selfiegram[87928:2176135] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Receiver (<Selfiegram.SelfieListViewController: 0x7f84bdc031a0>) has no segue with identifier 'showSettings''
*** First throw call stack:
(
    0   CoreFoundation                      0x00007fff23c7127e __exceptionPreprocess + 350
    1   libobjc.A.dylib                     0x00007fff513fbb20 objc_exception_throw + 48
    2   UIKitCore                           0x00007fff47a1704f -[UIViewController shouldPerformSegueWithIdentifier:sender:] + 0
    3   Selfiegram                          0x000000010ca95453 $s10Selfiegram24SelfieListViewControllerC15settingsClickedyyF + 115
    4   Selfiegram                          0x000000010ca9549b $s10Selfiegram24SelfieListViewControllerC15settingsClickedyyFTo + 43
    5   UIKitCore                           0x00007fff48093fff -[UIApplication sendAction:to:from:forEvent:] + 83
    6   UIKitCore                           0x00007fff476ba413 __45-[_UIButtonBarTargetAction _invoke:forEvent:]_block_invoke + 88
    7   UIKitCore                           0x00007fff476ba281 -[_UIButtonBarTargetAction _invoke:forEvent:] + 237
    8   UIKitCore                           0x00007fff48093fff -[UIApplication sendAction:to:from:forEvent:] + 83
    9   UIKitCore                           0x00007fff47a6c00e -[UIControl sendAction:to:forEvent:] + 223
    10  UIKitCore                           0x00007fff47a6c358 -[UIControl _sendActionsForEvents:withEvent:] + 398
    11  UIKitCore                           0x00007fff47a6b2b7 -[UIControl touchesEnded:withEvent:] + 481
    12  UIKitCore                           0x00007fff480cebbf -[UIWindow _sendTouchesForEvent:] + 2604
    13  UIKitCore                           0x00007fff480d04c6 -[UIWindow sendEvent:] + 4596
    14  UIKitCore                           0x00007fff480ab53b -[UIApplication sendEvent:] + 356
    15  UIKitCore                           0x00007fff4812c71a __dispatchPreprocessedEventFromEventQueue + 6847
    16  UIKitCore                           0x00007fff4812f1e0 __handleEventQueueInternal + 5980
    17  CoreFoundation                      0x00007fff23bd4471 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
    18  CoreFoundation                      0x00007fff23bd439c __CFRunLoopDoSource0 + 76
    19  CoreFoundation                      0x00007fff23bd3b74 __CFRunLoopDoSources0 + 180
    20  CoreFoundation                      0x00007fff23bce87f __CFRunLoopRun + 1263
    21  CoreFoundation                      0x00007fff23bce066 CFRunLoopRunSpecific + 438
    22  GraphicsServices                    0x00007fff384c0bb0 GSEventRunModal + 65
    23  UIKitCore                           0x00007fff48092d4d UIApplicationMain + 1621
    24  Selfiegram                          0x000000010ca8a94b main + 75
    25  libdyld.dylib                       0x00007fff5227ec25 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb) 

Environment

  • XCode 11.3.1

  • Swift 5

Reason

You must add a segue to connect view controllers in xcode or iOS programming.

What is a segue?

According to this artictle:

A segue defines a transition between two view controllers in your app’s storyboard file. The starting point of a segue is the button, table row, or gesture recognizer that initiates the segue. The end point of a segue is the view controller you want to display. A segue always presents a new view controller, but you can also use an unwind segue to dismiss a view controller.

image: ../Art/segue_defined_2x.png

Normally , you don’t need to trigger the segue programmatically, the segue is trigger automatically if you create it from the story board. But sometimes, you want to trigger it manually, you can do as follows:

Solution

Step 1: Create a segue to connect two view controllers

You can just control-drag from the source view controller to the destination view controller, when the pop window shows, just select “show”, then a segue is created!

image-20200929135534378

Then , from the storyboard’s hierarchy view, you can see the segue is listed in the view.

Remember to set the identifier in the attributes view of the segue, for example ,name it “showSettings”.

Step 2: Trigger the segue when something happens

Here we trigger the segue when user clicked a button in the navigation bar. We add a menu button in the navigation bar like this:

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let settingsButton = UIBarButtonItem(title: "Settings", style: .plain, target: self, action: #selector(settingsClicked))
        navigationItem.rightBarButtonItems = [settingsButton] 
        }
        ....
    }

Then we create a function named “settingsClicked” to response to the settingsButton’s click event:

    @objc func settingsClicked() {
        performSegue(withIdentifier: "showSettings", sender: self)
    }