> For the complete documentation index, see [llms.txt](https://prodigi.gitbook.io/bootcamp/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://prodigi.gitbook.io/bootcamp/lesson-4-swift.md).

# Lesson 4 - Swift

## MVC (Model, View, Controller)

The **Model-View-Controller (MVC)** is an architectural pattern that separates an application into three main logical components: the model, the view, and the controller.

Each of these components are built to handle specific development aspects of an application. MVC is one of the most frequently used industry-standard web development framework to create scalable and extensible projects.

![](/files/-LFyiO7QlzppSH_5E5ou)

### Models

The objects that will be used to transport data.

### Views

Responsible to handle all UI interactions.

### Controllers

Responsible to handle all business code.

You can use the [MVC Base project](https://github.com/ProDigi-Developement/bootcamp/tree/mvc/base) as reference for your personal project.

## Calling a RESTful API

As a reference you can check the [Sample App code](https://github.com/ProDigi-Developement/bootcamp/tree/oop/swift-sample-app).

* Structuring calls
  * Create a simple and exclusive method to call the backend. On our example the function *fetch*
  * ```swift
    private func fetch(url: URLRequest, onSuccessScenario onSuccess: @escaping FetchSuccessScenario, onFailScenario onFail: @escaping FetchFailScenario) {
    ```

    The fetch method receives as parameters an URL variable of the type URLRequest and two callbacks to be able to return values on success and fail scenarios.
* Call backend
  * Implement the fetch method body code. On our example the code is
  * ```swift
    let config = URLSessionConfiguration.default
    let session = URLSession(configuration: config)

    let task = session.dataTask(with: url, completionHandler: { (data, response, error) in
        if let errorUnwrapped = error {
            onFail(errorUnwrapped.localizedDescription)
        } else {
            guard let httpResponse = response as? HTTPURLResponse else {
                onFail("Failed to parse HTTPURLResponse object")
                return
            }

            guard httpResponse.statusCode == 200 else {
                onFail("Failed to receive status code 200. Received: \(httpResponse.statusCode)")
                return
            }

            if let dataUnwrapped = data {
                onSuccess(dataUnwrapped)
            } else {
                onFail("No data from response.")
            }
        }
    })

    task.resume()
    ```

    The fetch body method is a generic code to handle any call and delivery the data from the response object. We have to create a DataTask object using the Session object and also we have to implement the **completitionHandler**, because only on this way we can handle properly the response from backend.
* Testing Class

  * Let's test the fetch method using the <https://randomuser.me/api>

  ```swift
  public func fetchUsers() {
      if let url = URL(string: "https://randomuser.me/api?results=20") {
          self.userList = [User]()

          let requestUrl = URLRequest(url: url)
          requestUrl.httpMethod = "GET"

          self.fetch(url: requestUrl, onSuccessScenario: onFetchUserSuccess, onFailScenario: onFetchUserFail)
      } else {
          // Call the delegate to notify the view of fail on fetch
          self.delegate?.fetchUsersFailed(errorMessage: "Not possible to create the URL object")
      }
  }

  // MARK: Fetch Users callbacks
  private func onFetchUserSuccess(data: Data) {
      do {
          // Convert the data object to users
          let userList = try self.convertToUsers(withData: data)

          // Fill the Controller user list
          self.userList = userList

          // Call the delegate to notify the view of success fetch
          self.delegate?.fetchedAllUsers()
      } catch {
          // Call the delegate to notify the view of fail on fetch
          self.delegate?.fetchUsersFailed(errorMessage: "Not possible to convert the JSON to User objects")
      }
  }

  private func onFetchUserFail(error: String) {
      // Call the delegate to notify the view of fail on fetch
      self.delegate?.fetchUsersFailed(errorMessage: error)
  }
  ```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://prodigi.gitbook.io/bootcamp/lesson-4-swift.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
