Beagle v1.5 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 an “ActivityIndicator” when the screen is loading and does nothing. When an error happens, you can override this method to handle errors properly.
When overriding, if you want to preserve loading behavior, a “super” implementation should be called or you can customize a loading behavior by yourself.
Check out below the Beagle Navigation Controller class:
open class BeagleNavigationController: UINavigationController {
open func serverDrivenStateDidChange(
to state: ServerDrivenState,
at screenController: BeagleController
) {
switch state {
case .started:
view.showLoading(.whiteLarge)
case .finished:
view.hideLoading()
case .success, .error:
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
}
}
class CustomBeagleNavigationController: BeagleNavigationController {
private var errorView = ErrorView(message: nil) { }
override func serverDrivenStateDidChange(
to state: ServerDrivenState,
at screenController: BeagleController
) {
super.serverDrivenStateDidChange(to: state, at: screenController)
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 instantiating the BeagleScreenViewController, you can pass the controllerId
“CustomBeagleNavigation” so that your BeagleScreenViewController use 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.