Skip to content
This repository has been archived by the owner on Sep 6, 2018. It is now read-only.

Typed segues on a per scene basis #79

Closed
wants to merge 11 commits into from
Closed

Conversation

djbe
Copy link
Member

@djbe djbe commented Aug 23, 2017

SwiftGenKit PR: SwiftGen/SwiftGenKit#54

Uses the improvements added in SwiftGenKit to generate extensions for non-base classes (UIKit/AppKit), so that a user can:

  • Perform a segue safely with an enum of segues that start from that scene (you can no longer incorrectly start a segue from a VC that doesn't support it).
  • Prepare for a segue in a type safe way:
    • Have an exhaustive list of possible cases, including one for unnamed segues.
    • Get the segue's destination in the correct type (no need to cast it).
    • Get the segue itself as the correct subclass if you're using custom segues.

For performing a segue, the user goes from:

perform(segue: StoryboardSegue.MyStoryboard.nextStep)

To:

perform(segue: .nextStep)

For preparing for a segue, the user goes from:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let segueEnum = StoryboardSegue.MyStoryboard(segue: segue.identifier ?? "") {
        switch segueEnum {
        case .nextStep:
            guard let destination = segue.destination as? NextStepViewController else { return }
            // destination is casted version
        case .login:
            guard let destination = segue.destination as? LoginViewController else { return }
            // destination is casted version
        default:
            // Handle segues that are for other scenes
        }
    } else {
        // Handle unnamed segues
    }
}

To:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    switch TypedStoryboardSegue(segue: segue) {
    case .nextStep(let destination):
        // destination is casted version
    case .login(let destination):
        // destination is casted version
    case .unnamedSegue:
        // This case is added if you have unnamed segues (with identifier "")
    }
}

@djbe
Copy link
Member Author

djbe commented Aug 23, 2017

@AliSoftware proposed another idea, that we could add to this template (or an alternative one):

protocol MyViewControllerTypedStoryboardSegue {
  func prepareSegueForEmbed(destination: EmbedDestinationVC)
  func prepareSegueForModal(destination: ModalDestionationVC)func prepare(for segue: NSStoryboardSegue, sender: Any?)
}
extension MyViewControllerTypedStoryboardSegue {
  func prepare(for segue: NSStoryboardSegue, sender: Any?) {
    /* generate that switch/case implementation here which calls the proper prepareSegueForXXX(destionation:) method */
  }
}

There could be issues here because of @objc dispatch and stuff, but could be interesting.

Another proposal was:

/* Generated by SwiftGen */
protocol MyViewControllerTypedStoryboardSegue {
  func prepareSegueForEmbed(destination: EmbedDestinationVC)
  func prepareSegueForModal(destination: ModalDestionationVC)func prepare(for segue: NSStoryboardSegue)
}
extension MyViewControllerTypedStoryboardSegue {
  func prepare(for segue: NSStoryboardSegue) {
    /* generate that switch/case implementation here which calls
        the proper prepareSegueForXXX(destionation:) method */
  }
}

/* Added by the user */
extension MyViewController: MyViewControlelrTypedStoryboardSegue {
  @objc func prepare(for segue: NSStoryboardSegue, sender: Any?) {
    self.prepare(for: segue)
  }
}

I'd probably rename the function here, because users want access to the sender argument so we'd need to pass it along.

Had to change a class name because of https://bugs.swift.org/browse/SR-898 (module and class name with same name)
@djbe
Copy link
Member Author

djbe commented Aug 23, 2017

I'm going to wait on #36 to fix the last compilation issue (for the ignore-import case), as it needs the same per-file logic to add definitions.

@djbe
Copy link
Member Author

djbe commented Dec 10, 2017

Archiving this in favour of SwiftGen/SwiftGen#364.

@djbe djbe closed this Dec 10, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant