Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A decoupled way to propagate URL opening in an iOS app over the Responder chain
/// Conforming to this protocol allows for URL handling
protocol URLHandler {
/// Handle a URL
///
/// - Parameter url: The propagated url
/// - Returns: The handled status
func handleURL(_ url: URL, options: [UIApplication.OpenExternalURLOptionsKey : Any], completionHandler completion: ((Bool) -> Void)?)
}
// MARK: - Error Propagation
extension UIResponder {
/// Propagates a URL through the responder chain.
///
/// - Parameters:
/// - url: The URL to propagate
/// - options: A dictionary of options to use when opening the URL. For a list of possible keys to include in this dictionary, see URL Options.
/// - completion: The block to execute with the results. Provide a value for this parameter if you want to be informed of the success or failure of opening the URL.
func propagateURL(_ url: URL,
options: [UIApplication.OpenExternalURLOptionsKey : Any] = [:],
completionHandler completion: ((Bool) -> Void)? = nil) {
// Check if we have a next, otherwise return `false` to indicate that the operation failed
guard next != nil else {
completion?(false)
return
}
// Check if the next responder can handle URLs
guard let urlHandler = next as? URLHandler else {
// If not then carry on the propagation of the URL
next?.propagateURL(url, options: options, completionHandler: completion)
return
}
// Ask the Next to handle the URL
urlHandler.handleURL(url, options: options) { [weak self] (status) in
if status == false {
// If the next failed to handle the URL, continue the propagation of the URL
self?.next?.propagateURL(url, options: options, completionHandler: completion)
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment