Search documentation of mob

# Mob.App behaviour (mob v0.6.18)

Copy Markdown View Source

Behaviour for Mob application entry point.

## Usage

    defmodule MyApp do
      use Mob.App

      def navigation(_platform) do
        stack(:home, root: MyApp.HomeScreen)
      end

      def on_start do
        Mob.Screen.start_root(MyApp.HomeScreen)
        Mob.Dist.ensure_started(node: :"my_app@127.0.0.1", cookie: :secret)
      end
    end

`use Mob.App` generates a `start/0` that the BEAM entry point calls. It handles all framework initialization (native logger, navigation registry) before delegating to `on_start/0`. App code only goes in `on_start/0`.

## Navigation

Implement `navigation/1` to declare the app's navigation structure. Use the helper functions `stack/2`, `tab_bar/1`, and `drawer/1`:

    def navigation(:ios),     do: tab_bar([stack(:home, root: HomeScreen), ...])
    def navigation(:android), do: drawer([stack(:home, root: HomeScreen), ...])
    def navigation(_),        do: stack(:home, root: HomeScreen)

All `name` atoms used in stacks become valid `push_screen` destinations without needing to reference modules directly.

## Summary

### Callbacks

navigation(platform)
on_start()

App-specific startup hook. Called by the generated `start/0` after all framework initialization is complete.

### Functions

configure_ios_inet_db()

Apply the iOS-only `:inet_db` workaround so distribution, RPC, and TCP-by-hostname don't crash on the first lookup.

drawer(branches)

Declare a side drawer containing multiple named stacks.

stack(name, opts)

Declare a navigation stack.

tab_bar(branches)

Declare a tab bar containing multiple named stacks.

## Callbacks

# navigation(platform)

    @callback navigation(platform :: atom()) :: map()

# on_start()

(optional)

    @callback on_start() :: term()

App-specific startup hook. Called by the generated `start/0` after all framework initialization is complete.

Override to start your root screen, configure Erlang distribution, set the Logger level, etc. The default implementation is a no-op.

## Functions

# configure_ios_inet_db()

    @spec configure_ios_inet_db() :: :ok

Apply the iOS-only `:inet_db` workaround so distribution, RPC, and TCP-by-hostname don't crash on the first lookup.

iOS sandboxes any app that isn't Apple's own and refuses `execve` of binaries the app didn't get a special pass for. BEAM's default `:native` hostname-resolution path spawns the `inet_gethost` port program — exactly the kind of `execve` iOS rejects — so the very first `:inet.getaddr/2` call (transitively reached by `Node.connect`, `:erpc.call`, `gen_tcp.connect/3` with a binary host, etc.) crashes the calling process with `:badarg`. The simulator hits the same failure for a related but distinct reason: `inet_gethost` doesn't live at the path BEAM expects under the mob iOS sim OTP layout. Either way, the fix is the same.

Switching the lookup chain to `[:file]` keeps everything in BEAM's in-process name table — no port program, no fork, no `execve`. We also seed `localhost` so apps using `@localhost` node names (or any `gen_tcp` call that resolves `"localhost"`) work without further setup.

Called automatically by the macro-generated `start/0` before anything else, so app `on_start/0` code never has to think about it. Apps that need outbound DNS (Req / Finch / Mint to arbitrary hosts) can layer `Mob.DNS.configure_pure_beam/1` on top — it upgrades the chain to `[:file, :dns]` and seeds fallback nameservers, while the file-table entries we add here keep winning.

Other platforms (`:android`, `:host`) are unaffected — BEAM's native resolver works there. Safe to call on host BEAM where the NIF isn't loaded; rescues the `UndefinedFunctionError` / `ErlangError` and returns `:ok`.

# drawer(branches)

    @spec drawer([map()]) :: map()

Declare a side drawer containing multiple named stacks.

Renders as a ModalNavigationDrawer on Android. iOS uses a custom slide-in panel (native UIKit drawer support deferred).

# stack(name, opts)

    @spec stack(
      atom(),
      keyword()
    ) :: map()

Declare a navigation stack.

`name` is the atom identifier used with `push_screen/2,3`, `pop_to/2`, and `reset_to/2,3`. The `:root` option is the module mounted when the stack is first entered.

Options:

- `:root` (required) — screen module that is the stack's initial screen
- `:title` — optional display label shown in tabs or drawer entries

# tab_bar(branches)

    @spec tab_bar([map()]) :: map()

Declare a tab bar containing multiple named stacks.

Each branch must be a `stack/2` map. Renders as a bottom NavigationBar on Android and a UITabBarController on iOS.