Beagle v1.6 is no longer actively maintained. The documented version you are viewing may contain deprecated functionality. For up-to-date documentation, see the latest version .
Beagle Navigation Controller is a class like the UINavigationController
, but more focused on handle the server-driven screen state when it starts or finishes.
The method serverDrivenStateDidChange()
is the entry point to handle screen state changes.
The default implementation shows a UIActivityIndicatorView
when the screen is loading. It also shows a default error screen with errors treatment and a retry button.
When overriding, if you want to preserve a loading and error behavior, a super
implementation should be called to represent the superclass BeagleNavigationController
or you can customize a loading and handle the error behavior by yourself.
Both implementations can be seen in the examples below.
Check out below the Beagle Navigation Controller class:
open class BeagleNavigationController: UINavigationController {
private var errorView = BeagleErrorView(message: nil) { }
open func serverDrivenStateDidChange(
to state: ServerDrivenState,
at screenController: BeagleController
) {
switch state {
case .started:
view.showLoading(.whiteLarge)
case .finished:
view.hideLoading()
case .error(let serverDrivenError, let retry):
let message = getServerDrivenErrorMessage(from: serverDrivenError)
guard let retry = retry else { return }
if !view.subviews.contains(errorView) {
errorView = BeagleErrorView(message: message, retry: retry)
errorView.present(in: view)
} else {
errorView.addRetry(retry)
}
case .success:
break
}
}
}
The ServerDrivenState is an enum that typifies the screen state. See its structure below:
public typealias BeagleRetry = () -> Void
public enum ServerDrivenState {
case started
case finished
case success
case error(ServerDrivenState.Error, BeagleRetry)
}
extension ServerDrivenState {
public enum Error: Swift.Error {
case remoteScreen(Request.Error)
case action(Swift.Error)
case lazyLoad(Request.Error)
case submitForm(Request.Error)
case webView(Swift.Error)
case declarativeText
}
}
When preserving loading and error behavior, a super
implementation with the method serverDrivenStateDidChange
should be called to represent the superclass BeagleNavigationController.
class CustomBeagleNavigationController: BeagleNavigationController {
override func serverDrivenStateDidChange(
to state: ServerDrivenState,
at screenController: BeagleController
) {
super.serverDrivenStateDidChange(to: state, at: screenController)
}
}
You will see below an example of a class inherited from BeagleNavigationController
. The serverDrivenStateDidChange
method is overridden in it and handles the error state differently.
class CustomBeagleNavigationController: BeagleNavigationController {
private var errorView = ErrorView(message: nil) { }
override func serverDrivenStateDidChange(
to state: ServerDrivenState,
at screenController: BeagleController
) {
guard case let .error(serverDrivenError, retry) = state else { return }
let message: String
switch serverDrivenError {
case .remoteScreen(let error), .lazyLoad(let error), .submitForm(let error):
switch error {
case .networkError(let messageError):
message = messageError.localizedDescription
case .decoding(let messageError):
message = messageError.localizedDescription
case .loadFromTextError, .urlBuilderError:
message = error.localizedDescription
}
case .action(let error):
message = error.localizedDescription
default:
message = "Unknow Error."
}
if !view.subviews.contains(errorView) {
errorView = ErrorView(message: message, retry: retry)
errorView.present(in: view)
} else {
errorView.addRetry(retry)
}
}
}
let dependencies = BeagleDependencies()
dependencies.navigation.registerNavigationController(
builder: CustomBeagleNavigationController.init,
forId: "CustomBeagleNavigation"
)
Beagle.dependencies = dependencies
Now, when you are instantiating the BeagleScreenViewController, you can pass the controllerId
“CustomBeagleNavigation” so that your BeagleScreenViewController uses your CustomBeagleNavigationController
.
func screenController() -> UIViewController {
let screen = Screen(
child: Text()
)
return BeagleScreenViewController(
.declarative(screen),
controllerId: "CustomBeagleNavigation"
)
}
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.