Home > Net >  Creating an an enum for segue identifiers
Creating an an enum for segue identifiers

Time:10-04

How would I go about extending an NSObject, NSStoryboardSegue.Identifier, to provide a set of cases as potential parameter types?

extension NSStoryboardSegue.Identifier {
  enum identifier: String {
    case showHelpWindow
  }
}    

extension ViewController {
      
  override func prepare(for segue: NSStoryboardSegue, sender: Any?) {
    if (segue.identifier == "showHelpWindow") {
      // What I have now
    }
    
    if segue.identifier == .showHelpWindow {
      // What I'm trying to get
    }
  }

  func showHelpWindow() {
    // What I have now
    performSegue(withIdentifier: "showHelpWindow", sender: self)
    // What I'm trying to get
    performSegue(withIdentifier: .showHelpWindow, sender: self)
  }
      
}

CodePudding user response:

Define a protocol

protocol SegueHandlerType {
    associatedtype SegueIdentifier : RawRepresentable
}

and a protocol extension to overload performSegue. The segueIdentifer(for method is to get the identifier if there are multiple segues in the controller

extension SegueHandlerType where Self : UIViewController, SegueIdentifier.RawValue == String {
    
    func performSegue(withIdentifier segueIdentifier : SegueIdentifier, sender: Any?) {
        performSegue(withIdentifier: segueIdentifier.rawValue, sender: sender)
    }
    
    func segueIdentifer(for segue : UIStoryboardSegue) -> SegueIdentifier {
        guard let identifier = segue.identifier, let segueIdentifier = SegueIdentifier(rawValue: identifier) else {
            fatalError("Invalid segue identifier \(segue.identifier!)")
        }
        return segueIdentifier
    }
} 

To use it adopt the protocol in the view controller and declare an enum for the identifiers

class ViewController: UIViewController, SegueHandlerType {

    enum SegueIdentifier : String {
        case showHelpWindow, showSomethingElse
    }

...

    func showHelpWindow() {

        performSegue(withIdentifier: .showHelpWindow, sender: self)
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
          if case .showHelpWindow = segueIdentifer(for:segue) {


          }
    }
}
    

CodePudding user response:

You don't actually need to extend NSStoryboardSegue.Identifier at all. Just create your own enum:

enum SegueIdentifier: String {
    case mySegue
}

Add a custom == operator so that it can be compared with segue.identifier:

static func ==(lhs: String?, rhs: SegueIdentifier) -> Bool {
    lhs == rhs.rawValue
}

Then extend NSViewController to add an overload of performSegue that takes SegueIdentifier:

extension NSViewController {
    func performSegue(withIdentifier identifier: SegueIdentifier, sender: Any?) {
        performSegue(withIdentifier: identifier.rawValue, sender: sender)
    }
}

Usage:

class MyViewController: NSViewController {
    override func prepare(for segue: NSStoryboardSegue, sender: Any?) {
        if segue.identifier == .mySegue {
            // ...
        }
    }
    
    func foo() {
        performSegue(withIdentifier: .mySegue, sender: nil)
    }
}
  • Related