iosdev

coordinatingResponder with no Coordinators in sight

Learn how to get the main benefit of my Coordinator implementation without actually using the library or the pattern.

The best aspect of the Coordinator library is coordinatingResponder messaging (see the explanation in the README). Once you get used to it, it’s a pain to revert back to other techniques — all of them require more code than this. There’s really nothing clearer and simpler to output some data or continue user scenario than calling a method like accountLogin() from previous post.

All my UI code is already written with this in mind thus it’s only natural I want to apply that everywhere:

While it seems possible to set anything you want as the value of NSExtensionPrincipalClass in extension’s Info.plist file, it turns out thât class must be subclass of UIViewController. During the extension’s loading process, UIKit is explicitly targeting UIViewController’s methods, it expects that .view is present etc.

Thus I can’t use Coordinator subclass as principal class for the extension. Why would I even want that?

I have already built a series of UIViewControllers that display content of incoming push notifications when received inside the app. They are controlled by a single Coordinator instance. I wanted to use all that code to display thât same content outside the app; say when you perform 3D Touch over the notification in Notification Center.

The app I’m working on has multiple push notification categories. To avoid building separate ContentExtension target for each category, I specify an array of category values (you can do that for UNNotificationExtensionCategory in extension’s Info.plist) and use just one target; then switch over the category value and load appropriate UIVC instance inside the Coordinator. Coordinator I have is already properly wired to read stuff the UI needs from shared Core Data, to call web service APIs etc.

All of that already works, inside the main app. Because of app extension limitation, I had to resort to custom container UIViewController which acts as Coordinator. Which lead me to this revelation, so obvious in hindsight:

you don’t need Coordinator to get the benefit of coordinatingResponder messaging

coordinatingResponder messaging already works with embedded child controllers regardless of UIVC being inside Coordinator or not. But if Coordinating protocol is not even present, this file from the library can’t be used as it is.

But this can:

public extension UIResponder {
	@objc public var coordinatingResponder: UIResponder? {
		return next
	}
}

extension UIViewController {
	override open var coordinatingResponder: UIResponder? {
		guard let parentController = self.parent else {
			guard let presentingController = self.presentingViewController else {
				return view.superview
			}
			return presentingController as UIResponder
		}
		return parentController as UIResponder
	}
}

That is all the code you need.

I will, of course, continue using Coordinators in my iOS/tvOS apps. They are really good tool to manage data flows without the UIViewController overhead.

But if for any reason you can’t or don’t want to use them, you can use just the code above to still get the main benefit of the library. I love flexible programming techniques like that.