Xcode 6 Storyboard Unwind Segue with Swift Not Connecting to Exit

前端 未结 11 1783
栀梦
栀梦 2020-12-02 09:20

When trying to connect a Navigation Bar Button to the Exit item of a ViewController in Xcode 6 (not really sure if it\'s an Xcode 6 problem but worth mentioning as it is in

相关标签:
11条回答
  • 2020-12-02 09:34

    This is a known issue with Xcode 6:

    Unwind segue actions declared in Swift classes are not recognized by Interface Builder

    In order to get around it you need to:

    1. Change class MyViewController to @objc(MyViewController) class MyViewController
    2. Create an Objective-C header file with a category for MyViewController that redeclares the segue action.

      @interface MyViewController (Workaround)
      - (IBAction)unwindToMyViewController: (UIStoryboardSegue *)segue;
      @end
      
    3. In the storyboard, select the instance of MyViewController, clear its custom class, then set it back to MyViewController.

    After these steps you are able to connect buttons to the exit item again.

    Xcode 6 Release Notes PDF, Page 10

    0 讨论(0)
  • 2020-12-02 09:37

    Instead of using the Objective-C workaround, Xcode 6 Beta 4, which can now be installed, supports the connection of unwind segues in the Interface Builder. You can update now from the iOS Dev center. Control-click and drag from the UI item you want to trigger the segue to the exit icon, and select the function unwindToSegue after having put the following code in the destination view controller.

    @IBAction func unwindToSegue (segue : UIStoryboardSegue) {}
    
    0 讨论(0)
  • 2020-12-02 09:37

    It appears that Xcode 6.1 has fixed this issue. You can now set up unwind segues in Swift with the following code:

    @IBAction func unwindToList(segue: UIStoryboardSegue) {
        // Nothing needed here, maybe a log statement
        // print("\(segue)")
    }
    

    This method - which can remain empty - needs to have a method signature with the UIStoryboardSegue type and not AnyObject or Interface Builder will not see it.

    For more detail check the TechNote 2298

    0 讨论(0)
  • 2020-12-02 09:37

    You may want to verify that the original controller destination that you're trying to unwind to is not embedded inside a Container object. Xcode 6 ain't having that.

    0 讨论(0)
  • 2020-12-02 09:42

    I was able to finally get it to work; the xcode6 IB is really fragile right now (crashes a lot too). I had to restart the IDE before I could connect the nav bar button item to the exit item. I ended up re-creating my test project and following the above suggestion (Xcode 6 Release Notes PDF, Page 10) to get it to work. In addition, when adding the .h file, I made sure to select my project target, which was unchecked by default. I also created my controller swift stub via the Cocoa Touch Class template (vs empty swift file). I used a modal segue in my nav controller.

    ListTableViewController.h

    #import <UIKit/UIKit.h>
    
    @interface ListTableViewController
    - (IBAction)unwindToList: (UIStoryboardSegue *)segue;
    @end
    

    ListTableViewController.swift

    import UIKit
    
    @objc(ListTableViewController) class ListTableViewController: UITableViewController {
    
        @IBAction func unwindToList(s:UIStoryboardSegue) {
            println("hello world");
        }
    
    }
    

    hope that helps

    0 讨论(0)
  • 2020-12-02 09:42

    The answers above rely on ObjC to fix the issue, I have found a pure Swift solution. While adding the segue handler in Swift allowed me to create the unwind segue in Interface Builder (Xcode 6.3), the handler was not being called.

    @IBAction func unwindToParent(sender: UIStoryboardSegue) {
        dismissViewControllerAnimated(true, completion: nil)
    }
    

    So after digging in, the canPerformUnwindSegueAction:fromViewController:withSender from the super class returns false. So I've overridden the implementation, and it works:

    override func canPerformUnwindSegueAction(action: Selector, fromViewController: UIViewController, withSender sender: AnyObject) -> Bool {
        return action == Selector("unwindToParent:")
    }
    

    Update
    The code above is incorrect, as I resolved the issue without overriding canPerformUnwindSegueAction:fromViewController:withSender. The fundamental error was to make the distinction between the presenting viewcontroller and the presented viewcontroller.

    When an unwind segue is initiated, it must first locate the nearest view controller in the navigation hierarchy which implements the unwind action specified when the unwind segue was created. This view controller becomes the destination of the unwind segue. If no suitable view controller is found, the unwind segue is aborted.
    source: Technical Note TN2298

    So, define the @IBAction on the presenting viewcontroller, not on the presented view controller. That way the segue will have meaningful values for the properties destinationViewController and sourceViewController as well, being respectively the presenting and presented viewcontroller.

    0 讨论(0)
提交回复
热议问题