Skip to content

Instantly share code, notes, and snippets.

@warren-gavin
Last active April 27, 2018 05:48
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save warren-gavin/3690c6b4c74bd92c9a1d791209df2985 to your computer and use it in GitHub Desktop.
Save warren-gavin/3690c6b4c74bd92c9a1d791209df2985 to your computer and use it in GitHub Desktop.
protocol StoryboardCoordinationDelegate: CoordinationDelegate {
func sourceViewControllerHadUserInteraction(source: UIViewController)
}
class ViewController: UIViewController, Coordinated {
var coordinationDelegate: CoordinationDelegate?
@IBAction func buttonTapped(_: AnyObject) {
let delegate = self.coordinationDelegate as? StoryboardCoordinationDelegate
delegate?.sourceViewControllerHadUserInteraction(self)
}
}
class MainStoryboardCoordinator: StoryboardCoordinationDelegate {
func sourceViewControllerHadUserInteraction(source: UIViewController) {
source.performSegueWithIdentifier("segue", sender: source)
}
func coordinateTransitionFrom(source: Coordinated, toDestination destination: UIViewController) {
}
}
class AppCoordinator {
func start(window: UIWindow?) {
UIStoryboardSegue.addCoordination()
let rootViewController = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController() as? ViewController
rootViewController?.coordinationDelegate = MainStoryboardCoordinator()
window?.rootViewController = rootViewController
}
}
class ViewController: UIViewController, Coordinated {
var coordinationDelegate: CoordinationDelegate?
}
class MainStoryboardCoordinator: CoordinationDelegate {
func coordinateTransitionFrom(source: Coordinated, toDestination destination: UIViewController) {
}
}
class AppCoordinator {
func start(window: UIWindow?) {
UIStoryboardSegue.addCoordination()
let rootViewController = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController() as? ViewController
rootViewController?.coordinationDelegate = MainStoryboardCoordinator()
window?.rootViewController = rootViewController
}
}
protocol CoordinationDelegate {
func coordinatedObjectHasStateChange(source: Coordinated)
}
protocol Coordinated {
var coordinationDelegate: CoordinationDelegate? { get set }
}
class ViewController: UIViewController, Coordinated {
var coordinationDelegate: CoordinationDelegate?
}
class Coordinator: CoordinationDelegate {
func coordinatedObjectHasStateChange(source: Coordinated) {
}
}
protocol CoordinationDelegate {
func coordinateTransitionFrom(source: Coordinated, toDestination destination: UIViewController)
}
protocol Coordinated {
var coordinationDelegate: CoordinationDelegate? { get set }
}
class ViewController: UIViewController, Coordinated {
var coordinationDelegate: CoordinationDelegate?
}
class Coordinator: CoordinationDelegate {
func coordinateTransitionFrom(source: Coordinated, toDestination destination: UIViewController) {
}
}
extension UIStoryboardSegue {
private struct Lock {
static var token: dispatch_once_t = 0
}
class func addCoordination() {
dispatch_once(&Lock.token) {
let originalPerformSelector = #selector(perform)
let swizzledPerformSelector = #selector(swizzledPerform)
method_exchangeImplementations(class_getInstanceMethod(UIStoryboardSegue.self, originalPerformSelector),
class_getInstanceMethod(UIStoryboardSegue.self, swizzledPerformSelector))
}
}
func swizzledPerform() {
defer {
self.swizzledPerform()
}
guard let sourceViewController = self.sourceViewController as? Coordinated else {
return
}
if var destinationViewController = self.destinationViewController as? Coordinated {
destinationViewController.coordinationDelegate = sourceViewController.coordinationDelegate
}
sourceViewController.coordinationDelegate?.coordinateTransitionFrom(sourceViewController,
toDestination: self.destinationViewController)
}
}
@fabiomassimo
Copy link

At line 9 of swizzled-segue.swift you get following compile error: Variable used within its own initial value

I'd propose following as easy fix:

    class func addCoordination() {
        dispatch_once(&Lock.token) {
            let originalPerformSelector = #selector(perform)
            let swizzledPerformSelector = #selector(swizzledPerform)

            method_exchangeImplementations(class_getInstanceMethod(UIStoryboardSegue.self, originalPerformSelector),
                                           class_getInstanceMethod(UIStoryboardSegue.self, swizzledPerformSelector))
        }
    }

@warren-gavin
Copy link
Author

Indeed. Nice catch, thanks for the help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment