Building a Cross-Platform eBook App in SCADE
Tags: scade, ios, android, mobile
Published: 2023-08-02 15:18:49

This tutorial aims at introducing mobile developers to developing a cross-platform e-reader app solely using Swift and SCADE.

The user interface of the eBook is inviting, and accessing it is quite simple. On the home page, it shows you four categories of books to make a selection from. Its navigation bar at the bottom also allows for an easy transition from one page to another. Users can also search for books and check out their overviews offline before proceeding to read the books online within the app.

Most importantly, in this tutorial, we will detail the step-by-step method of building this eBook app with SCADE. This is an excellent attempt to start with if you're new to SCADE development.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/89v2jgqyahghe8k6uogu.gif) 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x4knnfkpeda7xghmbadm.gif)

## Prerequisites

1. Download and install SCADE on your machine. You can find SCADE's latest version [here](https://www.scade.io/download/)
2. Learn how to create a SCADE project from scratch and give it any name of your choice.

In the event that you are absolutely uninitiated with the framework, click [here](https://docs.scade.io/docs/installation) to install SCADE on your computer using the official documentation, and click [here](https://docs.scade.io/docs/getting-started) to learn how to create your first project.

## Getting Started
Place the images in this [link](https://github.com/scadedoc/UgExamples/tree/master/SimplyE/Assets) into the Assets folder of your newly created project.

Additionally, create a folder named **managers** inside the project's root folder to hold all the necessary resources, including the classes (`Book class`, `Genre class`, and `CategoryManager`) and API callers that are required to complete the app's development.

## Step One: Let´s build our manager folder
Now, create the following three files inside the **managers** folder:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m7e9cisuyo2wvwtjstte.png)

Make sure to create the `Genre class`, `Book class` and `TrendingBookResponse struct` with each of them with their much-needed inheritance inside the `Book.swift` file.

Check this link in the project folder to see the [full code](https://github.com/scadedoc/UgExamples/blob/master/SimplyE/Sources/SimplyE/managers/Book.swift) of the code snippet given below:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zkx2abdqymgdendswpvh.png)

The next thing is to connect our **Book class model** to the API callers in the `ApiCaller.swift` file to generate data for each of our four book categories (such as Adventurous Books, Fantasy Books, Horror Books, and Health Books) and searched books.

View the [full code](https://github.com/scadedoc/UgExamples/blob/master/SimplyE/Sources/SimplyE/managers/APICaller.swift) for the provided code snippet:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0bznu0htkh065srlt5vx.png)

Create inside the `CategoryManager.swift` file a `CatalogManager class` to house the `loadDataAsync` and `fetchGenre` methods that we'll use in loading our books images and connect book categories data to our main view (`main.page`) respectively.

Check out the [full code](https://github.com/scadedoc/UgExamples/blob/master/SimplyE/Sources/SimplyE/managers/CategoryManager.swift) for the code snippet provided below.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zn8spqj2ysgyno8b5sqa.png)

Lastly, in this step, all the necessary methods we want for easy back-and-forth navigations of various pages of our app project are created inside the `Navigation.swift` file.

Check out the [complete code](https://github.com/scadedoc/UgExamples/blob/master/SimplyE/Sources/SimplyE/managers/Navigation.swift) of the `Navigation.swift` file's code sample supplied below:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0bmtsm552kdm5i3ghrgk.png)

## Step Two: Design the Launch Screen
Create another folder named login inside the root folder of the project. The login folder is where we are going to be putting the newly created `login page`:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qytnggpg9w95jsx82lcf.png)

We'll configure the `login page` inside the `start.swift` file to be the first screen visible to the users when the application's launched.

We designed the login page to display a logo sitting centrally on an orange background, while some data for the next pages are being fetched:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iy9sfmue09ufuw3dxuna.png)

Next is to write the logic that will make this page work. Inside the `Login.page.swift` file, we created the `postDisplayActions()` method to help users automatically navigate to the main page from the login page whenever the app is launched. 

That's not all, to make `postDisplayActions()` method effective, we ensured that it's called inside the `show()` method and not inside the `load()`method:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o8jog7ail0qtg142shod.png)

## Step Three: Build the Main Page
Let’s build our main page. The main page is divided into three rows. The first row is occupied by the `heroImage` and it works by randomly displaying the images of all books in each book category at a time. 

This `heroImage` is given a `300 height`. The `ctrlListBookCatalog` in the second row is a List-Control designed to accommodate all our four book categories. The `toolBar`, set to the far end of the page, is set to help users navigate to the `Search page` and `More page`:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sqbdveof8df4xpjdheli.png)

Below you have the `MainPageAdapter class` that binds data from the model to the `ctrlListBookCatalog` and `heroImage`.

We also have to initialize the `items` property of the `ctrlListBookCatalog` with data from every book category method declared inside the `MainPageAdapter class` so that all the visual controls defined inside the `ctrlListBookCatalog element`, via the `elementProvider object`, can display data assigned to them in the way they are configured. 

`heroImage` is defined inside the `showRandomBook() method` to depend on the random image data assigned to `selectedBook variable` from `randomBooks array`. Finally, we have to call the `showRandomBook() method` inside the `onEnter() method` so that `heroImage` can change to a different book image anytime a user enters the main page.

Check out the [complete code](https://github.com/scadedoc/UgExamples/blob/master/SimplyE/Sources/SimplyE/main.page.swift) for the code snippet provided below:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ohceua7hm721tip8t9nc.png)

## Step Four: Let's work on the Book's Pages
Once more, we'll create a new folder called `book pages` inside the project's root folder. This newly created folder will have a subset of folders that includes the `bookDetail page`, `bookWebview page`, and `search page`. Then, we'll create a page each into these subsets and call it `BookDetail.page`, `bookWebview.page`, and `search.page` respectively:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8a6orrm7lpy60fuu05oh.png)

### 4a. Design and define the Logic for BookDetail.page
The `BookDetail.page` is designed into a `navigationBar`, `listBookDetails`, `viewBookDescription`:
1. the `navigationBar` contains a `backButton` and a `detailsLabel`
2. `listBookDetails` is set up to retain vital information about a book, including the book's cover image, title, author, page count, read-book button, etc.
3. `viewBookDescription` is intended to only hold each book's overview and description labels
4. Three  `toolBarItems ` created inside the  `toolBar ` allow users to go to the search page, the More page, or return to the main page.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z7qdujenmuull3sb9rha.png)

We declared a `book` named variable of the type `Book` class inside the `BookDetailPageAdapter` class in the `BookDetail.page.swift` file. The `show()` method uses the `book` variable as a medium to pass data to all the needed properties on the `BookDetail.page`. However, if we don't downcast the `data` parameter of the `show()` method as an object of the `Book` model and also assign it to the `data` parameter of `super.show()`, these properties won't display their respective assigned values on the `BookDetail.page`.

View the [full code](https://github.com/scadedoc/UgExamples/blob/master/SimplyE/Sources/SimplyE/books%20page/BookDetail.page.swift) for the provided code snippet:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2az0lum3171sliprab4q.png)

### 4b. Set up the bookWebView.page and provide its logic
Only two rows make up the `BookDetail.page`, which contains the `navigationBar` and `webView` controls:
1. The `navigationBar`, which contains a `doneButton`, `titleLabel` and a `reloadButton`, occupies the first row
2. The `doneButton` is for returning to the books' detail page while the `reloadButton` is for reloading the webpage of a book
3. The `webView` control holds the second. We'll be using this `webView` to load our books webpages whenever a user clicks on the `readBookButton` on the `BookDetail.page`:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k95gq05qzkorgvfirjk8.png)

As we did for the `BookDetail.page.swift` file, we will also use the `show()` method inside the `bookWebView.page.swift` file. This simply means we'll need to connect the `webView` control to books' webpage data inside the `show()` method in order to successfully load the webpages of our books inside our app when a user clicks the `readBookButton` on the `BookDetail.page`:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uzywwrmuggnnkud5lils.png)

### 4c. Establish the search.page's layout and logic.
The `search.page` is divided into four rows, with the `horizontalTextboxView` in the first row, the `searchLabelTitle` in the second, the `ctrlListBooks` in the third, and the `toolBar` in the fourth, respectively:
1. The `horizontalTextboxView` houses the `textbox` control that listens to text changes when typing text into the keyboard to search for a particular book.
2. The `ctrlListBooks` loads all books in every category before it then loads the results of the related searched book in the `textbox`
3. The `toolBarItems` generated inside the `toolBar` enable users to return to the `main page` as well as access the `More page`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5s6qxhv0k6gmotbjfl4u.png)

We are going to use the `elementProvider` object to access and assign values to all the listed elements inside the `ctrlListBooks`. That's not all, there is also a need to initialize the `items` property of the `ctrlListBooks` with the results of all the books categories API data so that we can have a list of all our books categories on the `ctrlListBooks` of the `search.page` during launch time. 

Secondly, we also need to call the `onTextChanged()` method on the `textbox` control on the `search.page` so as to listen and use its `textbox.text` to fetch searched book results from the `getBook()` method and add the results to the `items` property of the `ctrlListBooks`.

Check out the [full code](https://github.com/scadedoc/UgExamples/blob/master/SimplyE/Sources/SimplyE/books%20page/search%20page/search.page.swift) for the code snippet shown below:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fr52dylgwkmmkzl5wj56.png)

## Conclusion
Now you can run the app and enjoy the newly built eBook app using SCADE! This is just a little bit of what you can do with SCADE.

The full source code of this tutorial can be found [here](https://github.com/scadedoc/UgExamples/tree/master/SimplyE).